Fabric: Inserting the hostname into a config file - fabric

I have a Fabric script I'm in the process of creating, and I want it to change the following line in a config file:
Hostname=localhost
I want it to include the actual host name, for example:
Hostname=mypc
I tried to do so with the following line:
fabric.contrib.files.sed(
'/etc/zabbix/zabbix_agentd.conf',
before='Hostname=localhost',
after='Hostname='"$HOSTNAME",
use_sudo=True, backup='')
But unfortunately, it won't work, and I've tried various combinations of quotes and double quotes. It will literally put "Hostname=$HOSTNAME" into the config file.

It won't work like that. The sed stuff is all inside single quotes. Just bind a name to the hostname value, and use Python interpolation to send it to the sed function. You might even be able to use the env.host setting. But an example of using this would look like this:
hostname = run("hostname -f")
fabric.contrib.files.sed(
'/etc/zabbix/zabbix_agentd.conf',
before='Hostname=localhost',
after='Hostname=%s' % hostname,
use_sudo=True, backup='')

Related

Using regex and pscp on AIX servers

I've been having lots of troubles using pscp and regex on AIX server.
As you can see, I am trying to use Putty's pscp to transfer file "stdout" to my local folder.
This usually works fine, but my problem is that I won't know exact same folder name so I need to use REGEX.
I've been told that possibly my regex was written for grep and that it wasn't supported by pscp.
What would be alternative then to write regex for pscp.
Error message is: "multiple-level wildcards unsupported"
pscp.exe -P 22 -pw krt_345 testuser#testserver5:"/app/log/s500/20201023/.\*/20201023-02\.2[0-9]\.[0-5][0-9]_s500_testuser.\*"/stdout C:\logs
regex only:
"/app/log/s500/20201023/.\*/20201023-02\.2[0-9]\.[0-5][0-9]_s500_testuser.\*"/stdout
With SCP protocol, the filemask in the path is resolved by the server. With a typical OpenSSH scp "server", you can use standard Linux glob masks. Definitely not regex. Though your mask is simple enough, that a simple glob mask 20201023-02.2[0-9].[0-5][0-9]_s500_testuser* would. But you can use glob mask for the last path component only. Not for the parent directory. What is what the "multiple-level wildcards unsupported" error message is trying to tell you.
So what you are doing is not doable with SCP. You would have to obtain the folder name using other means. Like using a shell commands over SSH.
And I belive you have asked for this already:
Finding folder name on a server using batch file
And based on your comments to the answer, you already know what you need to combine a shell command like find with scp. So I do not understand, why don't you ask for that.

Bash replace substring after first colon

I am trying to build a connection string that requires pulling 3 IP addresses from another config file. When I get those values, I need to replace the port on each. I plan to replace each port using simple Bash find and replace ${string/pattern/replacement} but my problem is I'm stuck on the best way to parse the pattern out of the IP.
Here is what I have so far:
myFile.config:
ip.1=ip-ip-1-address:1234:5678
ip.2=ip-ip-2-address:1234:5678
ip.3=ip-ip-3-address:1234:5678
Copying some other simple process, I found I can pull the value of each IP like this:
IP1=`grep "ip.1=" /path/to/conf/myFile.config | awk -F "=" '{print $2}'`
which gives me ip.1=ip-ip-1-address:1234:5678. However, I need to replace 1234:5678 with 6543 for example. I've been looking around and I found this awesome answer that detailed using Bash prefix substitution but that relies on knowing the parameter. for example, I would have to do it this way:
test=${ip1##ip-ip-1-address:}
which results in $test being 1234:5678. That's fine but maybe I don't know the IP address as the parameter, so I'm back to considering regex unless there's a way for me to use * as the parameter or something, but I have been unsuccessful so far. For regex, I have tried a bunch such as test=${ip1/(?<=:).*/}.
Note that ${ip1/(?<=:).*/} you tried is an example of string manipulation syntax that does not support regex, only specific patterns.
You seem to want
x='ip.1=ip-ip-1-address:1234:5678'
echo "${x%%:*}:6543" # => ip.1=ip-ip-1-address:6543
The ${x%%:*} takes the value of x and removes all chars from the end till the first : including it. :6543 is added to the result of this manipulation using "${x%%:*}:6543".
To extract that value, you may also use
awk '/^ip\.1=/{sub("^[^:]+:", "");print}' myFile.config
The awk command finds lines starting with ip.1= and then removes all text from the start till the first colon including the colon and only prints these values.

Use regex with grep to filter data from the output of a verbose command

I am working with a cloud environment and there is a command that will display all available information about VMs running. here is an example of some of the lines that pertain to one VM.
RESERVATION r-6D0F464B 170506678332 GroupD
INSTANCE i-E9B444A9 emi-376642D8 999.99.999.999 88.888.88.888 running lock_key 0 c1.xlarge 2013-06-17T18:40:56.270Z cluster01 eki-E7E242A3 monitoring-disabled 999.99.999.999 88.888.88.888 ebs
I need to be able to pull the i-********, emi-********, both IP address, its status, the lock_key, the c1.xlarge, and the monitoring-disabled/enabled.
I have been able to pull the whole line with some super simple regex but all of this is well beyond me. If there is another easier method of grabbing this data any suggestions are welcome.
Let's go by parts. Best way I can think of is redirecting the output to a file, in unix-like environments you do it like:
cat your-command > filename.txt
Second, you need to read the file line by line, I would use a python script or a perl script if you know any of those, or whatever language fits you.
Third, you can get values two different ways:
Read columns by position, you can get colums with a regex like: [^\s]+
Write regular expressions for every specific column, so for IP you could have something like this: ([0-9]{1,3}\.){4} for monitoring monitoring-([^\s]+) and so on.
As long as the fields will always be in the same order, all you need to is split on whitespace.
Pseudocode (well, it's ruby, but hopefully you get the idea):
vms = {}
File.open('vm-info').readlines.each do |line|
fields = line.split('\s+')
field_map = {}
vm_name = fields[<index_of_vm_name>]
field_map['emi'] = fields[<index_of_emi>]
field_map['ip_address'] = fields[<index_of_ip_address]
.
.
.
vms[vm_name] = field_map
end
After this, vms will be initialized to contain information about each vm. You can simply print them all out at this point, or continue running data manipulation on them.

Is it possible to use fabric.contrib.files.append() on a local file?

Trying to append() to a local file using Fabric.
I'd like to use
append('/etc/ssh_config', ['\n\nHost', '\n\tIdentityFile', '\n\User'])
But unfortunately it only tries on remote files
Attempting to wrap append within local(), like so:
local(append('/etc/ssh_config', ['\n\nHost', '\n\tIdentityFile', '\n\User']))
...fails miserably.
Don't believe so.
If you look at the source code for append it loops through the lines, escapes any regexes in the line and if the line is not already present in file based on a egrep check, it does a echo line >> file
It should be possible to wrap all this up a triple-quoted shell snippet that can then be passed to local

Regexp pattern matching IP and UserAgent in an Huge File

I have a huge log file that has a structure like this:
ip=X.X.X.X
userAgent=Firefox
-----
Referer=hxxp://www.bla.org
I want to create a custom output like this:
ip:userAgent
for ex:
X.X.X.X:Firefox
and the pattern will ignore lines which don't start with ip= and userAgent=. (these two must form a pair as i mentioned above.)
I am a newbie administrator and our client needs a sorted file immediately.
Any help will be wonderful.
Thanks.
^ip=(\d+(?:\.\d+){3})[\r\n]+userAgent=(.+)$
Apply in global + multiline mode.
Group 1 will contain the IP, group 2 will contain the user agent string.
Edit: The above expression can be simplified a bit, we can remove the IP address format checking - assuming that there will be nothing but real IP addresses in the log file:
^ip=(\d+\.?)+[\r\n]+userAgent=(.+)$
You can use:
^ip=((?:[0-9]{1,3}\.){3}[0-9]{1,3})$
And
^userAgent=(.*)$
Get the group 1 for both and you will have the desired data.
give it a try (this is in no way robust if there are lines where your log file differs from the example snippet above):
sed -n -e '/^ip=/ {s///
N
s/\nuserAgent=/:/
p
}' HugeFile > customoutput