Salt within for loop using incremental variable to set value in sed command - bash

What I'm trying to do is have salt set an internal host ip based on the current value of $i from the for loop. I've tried the following but was unsuccessful at modifying a network script that contains this line: 192.168.200.100 which resides in all 39 nodes.
for ((i=2; i<=30; i++)); do sudo salt -L "host$i.dev.mysite.com" cmd.run "sed -i "s/192.168.200.100/192.168.200.$i/" /etc/sysconfig/network-scripts/ifcfg-bond1; done"
Results I am looking is to have each hostX.dev.mysite.com bond1 files modified from 192.168.200.100 to 192.168.200.2
host2.dev.mysite.com /etc/sysconfig/network-scripts/ifcfg-bond1 = 192.168.200.2
host3.dev.mysite.com /etc/sysconfig/network-scripts/ifcfg-bond1 = 192.168.200.3
host4.dev.mysite.com /etc/sysconfig/network-scripts/ifcfg-bond1 = 192.168.200.4
host5.dev.mysite.com /etc/sysconfig/network-scripts/ifcfg-bond1 = 192.168.200.5
host6.dev.mysite.com /etc/sysconfig/network-scripts/ifcfg-bond1 = 192.168.200.6
host7.dev.mysite.com /etc/sysconfig/network-scripts/ifcfg-bond1 = 192.168.200.7
etc...

Something like this?
for ((i=2;i<=30;i++)); do
sudo salt -L "host${i}.dev.mysite.com" cmd.run "sed -r -i \"s#([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)[0-9]{1,3}\$#\1$i#\" /etc/sysconfig/network-scripts/ifcfg-bond1"
done

Related

why result set value not stored in arraylist in shell script

sample code below
psql -h $host -U postgres -d postgres -At -c "select partner_country_id as country , case when (threshold is null) then global_threshold else threshold end as threshold from ra_country_day_threshold " \
| while read -a Record
do
arrIN=(${Record[0]//|/ })
col1=${arrIN[0]}
col2=${arrIN[1]}
country_array["$col1"]="$col2"
echo "Col1:$col1 Col2:$col2"
done
echo "Elements:${country_array[#]}"
echo "length: ${#country_array[#]}"
Result
empty elements and length 0
The answer is simple, while command create a subprocess with its own context, if you create a new variable in that context, it will not be accessible outside of it.
Meaning the variable will not be accessible when you are outside the loop.
My suggestion is that you store the result inside a temporary file that will be available within all your script, then outside your loop, read that file.

How to run command in parallel way within a shell on a single ssh connection in a for loop

I am running a for loop around 3000 volumes within a ssh connection on a storage Server where this runs in a loop one by one, whereas i want the command vol show-footprint "$vols" -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1 to run parallel over multiple volumes at a time, lets say run it at 10 volumes in a go.
Here myTotalVol contains all 3k volume names like below:
myvol001
myvol002
myvol003
myvol004
myvol005
Below is the small for loop which is working.
for vols in $(cat myTotalVol);
do
echo -n "$vols " ;\
ssh storageServer01 "row 0; set -unit MB; \
vol show-footprint "$vols" -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1"; \
done
Please suggest if I can run the mentioned command over multiple volumes at a time which are kept in myTotalVol file.
Edit:
As asked by Mark Setchell in the comment section, hence below is just a view how its working ...
$ ssh store01
Last login time: 6/30/2022 10:49:41
store01::> row 0;set -unit MB
(rows)
store01::> vol show-footprint myvol001 -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1
vserver volume volume-blocks-footprint volume-blocks-footprint-bin0 volume-blocks-footprint-bin1
-------- -------------------- ----------------------- ---------------------------- ----------------------------
myvol001 myvol00198703MB 48272MB 51988MB
as you see the command vol show-footprint myvol001 -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1 here, i have to run this command over 3000 Volumes like i have myvol001 in this command so, myvol001 will go into the variable like i am using into the for loop and there i am using "$vols" which are referring to 3k vols from a file.
I'm not sure exactly what you are driving at, but you should be able to make a compound statement that generates the commands you want and then send that via ssh like this:
{ printf "row 0; set -unit MB;\n"
while read -r vol ; do
printf "vol show-footprint ${vol} -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1\n"
done < myTotalVol } | ssh store01
You can try it out and see what it produces if you put a comment character before the | like this:
{ ...
...
done < myTotalVol } # | ssh store01
Or you can do it with awk:
awk 'BEGIN{print "row 0; set -unit MB"} {print "vol show-footprint", $1, "-fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1"}' myTotalVol | ssh store01
Again, put # in front of | ssh store01 in order to see and check the output without sending it to ssh.

How to call a variable of string with spaces in a terraform provisioner?

I am trying to run terraform provisioner which is calling my ansible playbook , now I am passing public key as a variable from user . When passing public key it doesnt take the entire key and just ssh-rsa , but not a complete string.
I want to pass the complete string as "ssh-rsa Aghdgdhfghjfdh"
The provisioner in terraform which I am running is :
resource "null_resource" "bastion_user_provisioner" {
provisioner "local-exec" {
command = "sleep 30 && ansible-playbook ../../../../ansible/create-user.yml --private-key ${path.module}/${var.project_name}.pem -vvv -u ubuntu -e 'username=${var.username}' -e 'user_key=${var.user_key}' -i ${var.bastion_public_ip}, -e 'root_shell=/bin/rbash' -e 'raw_password=${random_string.bastion_password.result}'"
}
}
If i run playbook alone as:
ansible-playbook -i localhost create-user.yml --user=ubuntu --private-key=kkk000.pem -e "username=kkkkk" -e 'user_key='ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+GWlljlLzW6DOEo"' -e root_shell="/bin/bash"
it works,
But I want the string to be in a terraform variable which is passed in provisioner.
I want to have key copied to a file as
ssh-rsa AWRDkj;jfdljdfldkf'sd.......
and not just
ssh-rsa
You are getting bitten by the -e key=value splitting that goes on with the command-line --extra-args interpretation [citation]. What you really want is to feed -e some JSON text, to stop it from trying to split on whitespace. That will also come in handy for sufficiently complicated random string passwords, which would otherwise produce a very bad outcome when trying to pass them on the command-line.
Thankfully, there is a jsonencode() function that will help you with that problem:
resource "null_resource" "bastion_user_provisioner" {
provisioner "local-exec" {
command = <<SH
set -e
sleep 30
ansible -vvv -i localhost, -c local -e '${jsonencode({
"username"="${var.username}",
"user_key"="${var.user_key}",
"raw_password"="${random_string.bastion_password.result}",
})}' -m debug -a var=vars all
SH
}
}

Replace a text and IP address inside a file

I would like to write a script that reads a text file that has all the nodes listed in there:
node1
node2
node3
.
.
.
It creates a .conf file for each node in the
/etc/icinga2/zones.d/master/hosts/new/ directory
Copies the content of the file name windows-template into each
new conf file.
Then finds the phrase "hostname.hostdomain.com" in each conf file
and replaces that with the filename minus the .conf. So for example,
for node1, I will have node1.conf in which there is a phrase
"hostname.hostdomain.com" which needs to be replaced with node1
Then pings the hostname which is technically the filename minus
".conf" and replaces the 10.20.20.1 with the correct hostname.
I tried wrirting the script and part 1 and 2 work, part 3 works too but it replaces the hostname.hostdomain.com with "$f" which is not right. And I have no clue how to do number 4.
Can you please help?
Thank you
This is my windows-template.conf file:
object Host "hostname.hostdomain.com" {
import "production-host"
check_command = "hostalive"
address = "10.20.20.1"
vars.client_endpoint = name
vars.disks["disk C:"] = {
disk_partition = "C:"
}
vars.os = "Windows"
}
object Zone "hostname.hostdomain.com" {
endpoints = [ "hostname.hostdomain.com" ];
parent = "master";
}
object Endpoint "hostname.hostdomain.com" {
host = "10.20.20.1"
}
And this is my script:
#!/bin/bash
cd /etc/icinga2/zones.d/master/hosts/new
while read f; do
cp -v "$f" /etc/icinga2/zones.d/master/hosts/new/"$f.conf"
cp windows-template.conf "$f.conf"
chown icinga:icinga "$f.conf"
sed -i 's/hostname.hostdomain.com/$f/g' "$f.conf"
# git add "$f.conf"
# git commit -m "Add $f"
done < windows-list.txt
Thank you
You need double quotes for the shell to expand your variable. Try
sed -i "s/hostname.hostdomain.com/$f/g" "$f.conf"
Does this work for you?
#!/bin/bash
cd /etc/icinga2/zones.d/master/hosts/new
while read f; do
cp -v "$f" /etc/icinga2/zones.d/master/hosts/new/"$f.conf"
cp windows-template.conf "$f.conf"
chown icinga:icinga "$f.conf"
sed -i "s/hostname.hostdomain.com/$f/g" "$f.conf"
hostname=$( ssh -o StrictHostKeyChecking=no "username#$f" -n "hostname" )
mv "$f.conf" "${hostname}.conf"
# git add "$f.conf"
# git commit -m "Add $f"
done < windows-list.txt
Where username is your username, and I assume you copy your pub key to the hosts.

Bash script to PowerShell NET-SNMP

I have an issue changing an script I did in bash to powershell, the script is the following:
#! /bin/sh
for IPVAR in 172.27.41.202 172.27.41.203
do
TIEMPO=$(date +"%m-%d-%y")
FILENAME=${IPVAR}_${TIEMPO}
date +"%c" >> $FILENAME.txt
snmpget -v 2c -c public $IPVAR -mALL 1.3.6.1.4.1.41413.1.1.0 1.3.6.1.4.1.41413.1.4.0 1.3.6.1.4.1.41413.1.2.0 1.3.6.1.4.1.41413.1.3.0 1.3.6.1.4.1.41413.10.3.4.1.1.1 1.3.6.1.4.1.41413.10.3.4.1.2.1 1.3.6.1.4.1.41413.10.3.4.1.3.1 1.3.6.1.4.1.41413.10.3.4.1.4.1 1.3.6.1.4.1.41413.10.3.4.1.5.1 1.3.6.1.4.1.41413.10.3.4.1.6.1 1.3.6.1.4.1.41413.10.3.4.1.7.1 1.3.6.1.4.1.41413.10.3.4.1.8.1 1.3.6.1.4.1.41413.10.3.4.1.9.1 1.3.6.1.4.1.41413.10.3.4.1.10.1 >> $FILENAME.txt
done
In my Linux enviroment works fine but I installed NET-SNMP in a Windows Server because there is where we need the files to be but I can seem to make it work I did this:
$IPS = (10.96.90.2)
$TIEMPO = get-date -f yyyy-MM-dd
Foreach ($IPVAR in $IPS) {snmpget -v 2c -c public -m ALL $IPVAR 1.3.6.1.4.1.41413.1.1.0 1.3.6.1.4.1.41413.1.4.0 1.3.6.1.4.1.41413.1.2.0 1.3.6.1.4.1.41413.1.3.0 1.3.6.1.4.1.41413.10.3.4.1.1.1 1.3.6.1.4.1.41413.10.3.4.1.2.1 1.3.6.1.4.1.41413.10.3.4.1.3.1 1.3.6.1.4.1.41413.10.3.4.1.4.1 1.3.6.1.4.1.41413.10.3.4.1.5.1 1.3.6.1.4.1.41413.10.3.4.1.6.1 1.3.6.1.4.1.41413.10.3.4.1.7.1 1.3.6.1.4.1.41413.10.3.4.1.8.1 1.3.6.1.4.1.41413.10.3.4.1.9.1 1.3.6.1.4.1.41413.10.3.4.1.10.1 >> "$IPVAR_$TIEMPO".txt}
If I run only the "snmpget" command it works fine but I have troubles with the scripting part here.
Hope you can help me.
Regards,
Try the code below (this hasn't been tested as I don't have snmpget, but the method works with other command line apps):
$IPS = #('172.27.41.202', '172.27.41.203')
$IPS | ForEach-Object {
$snmpgetParams = #(
'-v', '2c' ,'-c' ,'public' ,'-m' ,'ALL', $_, '1.3.6.1.4.1.41413.1.1.0 1.3.6.1.4.1.41413.1.4.0 1.3.6.1.4.1.41413.1.2.0 1.3.6.1.4.1.41413.1.3.0 1.3.6.1.4.1.41413.10.3.4.1.1.1 1.3.6.1.4.1.41413.10.3.4.1.2.1 1.3.6.1.4.1.41413.10.3.4.1.3.1 1.3.6.1.4.1.41413.10.3.4.1.4.1 1.3.6.1.4.1.41413.10.3.4.1.5.1 1.3.6.1.4.1.41413.10.3.4.1.6.1 1.3.6.1.4.1.41413.10.3.4.1.7.1 1.3.6.1.4.1.41413.10.3.4.1.8.1 1.3.6.1.4.1.41413.10.3.4.1.9.1 1.3.6.1.4.1.41413.10.3.4.1.10.1'
)
$TIEMPO = Get-Date -f yyyy-MM-dd
$FILENAME="$_`_$TIEMPO`.txt"
snmpget #snmpgetParams | Set-Content $FILENAME -Force
}
Line 1 declares an array of IP addresses.
Line 2 starts a foreach loop which will iterate through each IP in the $IPS array.
Lines 3,4,5 create an array of parameters to pass to the snmpget command. The $_ parameter is the current IP address within the loop.
Line 7 sets the $TIEMPO variable with the date.
Line 8 sets the $FILENAME variable with the IP address, followed by an underscore, followed by the date. The backticks ` tell PowerShell to not treat the following characters as part of the preceding variable name. An example filename: 172.27.41.202_2016-08-31.txt
Line 10 calls the snmpget command. The #snmpgetParams 'splats' the parameter array. The output is piped into the Set-Content command, which, with the Force option creates or overwrites the file contents for that IP & date.
Line 11 closes the loop.

Resources