how to ssh a loop over several commands - bash

I am new to ssh so forgive me if my questions are trivial..i need to make a a remote computer execute a set of commands several times so i was thinking about making a loop using ssh ..the problem is i don't know do i save those commands in a file and loop on that file or can i like save them in ssh and just call them ..i am really troubled..also if i make a loop like this
i= 10
while i!= 0
execute command.text file ???
i--
How to i tell it to execute the file ?

Just try first on the shell in the remote machine to run the command you want.
You will find plenty of info over the internet about loops in shell/bash/csh/whatevershell:
For instance assuming bash run in the remote host (from: http://www.bashoneliners.com/ )
$ for ((i=1; i<=10; ++i)); do echo $i; done
Once you learn that, simply then take that statement to the ssh command from the machine you want to trigger the action:
$ ssh user#remotehost 'for ((i=1; i<=10; ++i)); do echo $i; done'

You can write a simple script that will execute needed commands, and path it to ssh.
For example:
script.sh, it will iterate over your bunch of commands 10 times:
for i in $(seq 10)
do
command1
command2
command3
done
and path it to remote server for execution:
$ ssh $SERVERNAME < script.sh

If you have this command.text file in which you have written all the commands in column (you can modify them with vi or vim and put them in column), you don't even need to do a loop, you can simply do:
cat command.text | awk '{print "ssh user#remotehost "$0" "}' | sh -x
For example if command.text contains:
ls -lart
cd /tmp
uname -a
This will let you do all commands written in the command.text by doing ssh user#remotehost.

Related

for loop is not running after ssh connection

I am trying to write a script which will do ssh to few hosts (via for loop) and run few commands on remote host with help of for another for loop.
I have written something like below but second for loop is not returning anything after doing ssh.
PS: ssh set-up has been done so no issues while doing ssh. Issue is with second for loop.
for ((i=11; i <= 16; i++))
do
echo $i
ssh abc$i.uk.com << EOF
cd /home
for j in `ls -1`
do
ls -lrt $j/*
done
EOF
done

for loop in remotely executed bash script does not work

I have a remote bash script, which goes through files using a for loop:
#!/bin/bash
for f in *.pdf;
do
echo $f
done
When executed locally:
server$./test.sh
1508.01585.pdf
1605.07683.pdf
When executed through ssh from a remote client:
client$ ssh user#server 'bash -c ~/papers/test.sh'
*.pdf
I have tried using ssh -T, bash -s, and nothing seems to work.
Please help!

How to run for loop inside heredoc while accessing remote machine

Here is my script in which I use local variable inside a remote machine using heredoc. But the loop under the heredoc takes the first variable value only. The loop runs fine inside the heredoc but with the same values.
#!/bin/bash
prod_web=($(cat /tmp/webip.txt));
new_prod_app_private_ip=($(cat /tmp/ip.txt));
no_n=($(cat /tmp/serial.txt));
ssh -t -o StrictHostKeyChecking=no ubuntu#${prod_web[0]} -p 2345 -v << EOF
set -xv
for (( x = 0; x < '${#no_n[#]}'; x++ ))
do
sudo su
echo '${no_n[x]}'
echo '${new_prod_app_private_ip[x]}'
curl -fIkSs https://'${new_prod_app_private_ip[x]}':9002 | head -n 1
done
EOF
So, my ip.txt file contains values like:
10.0.1.0
10.0.2.0
10.0.3.0
My serial.txt file:
9
10
11
So, my loop runs for only the first IP (present in /tmp/ip.txt) in the remote machine, three times. I want to run it for all the three IPs. My remote ip is present in the file /tmp/webip.txt.
Got stuck for a long time, any help is appreciated. Is there any other solution that I can go with?
There are 2 environments. On your local machine and on the remote machine. You need to think how to transfer data/variables/state/objects/handles between these machines.
If you set something on your local machine (ie. prod_web=($(cat /tmp/webip.txt));) and then just ssh to remote host (ie. ssh user#host 'echo "${prod_web[#]}"'), the variable will not be visible/exported to the remote machine. You can:
scp the files {ip,serial}.txt and execute the whole script on the remote machine, then cleanup , ie. remove the {ip,serial}.txt files from the remote machine
pass the files {ip,serial}.txt somehow merged/joined/pasted to the stdin of the ssh and then read up stdin on the remove machine
create all the commands to run on your local machine and then pass pre-prepared commands to remote machine, like ssh .... "$(for ...; do; echo curl ...; done)"
I would go with the second option, as I like passing everything using pipes and don't like to cleanup after me - removing temporary files in case of error can be a mess.
My script would probably look like this:
#!/bin/bash
set -euo pipefail
read -r host _ <webip.txt
paste serial.txt ip.txt | ssh -t -o StrictHostKeyChecking=no -p 2345 -v ubuntu#"$host" '#!/bin/bash
set -euo pipefail
while read -r no_n ip; do
for ((i = 0; i < no_n; ++i)); do
printf "%s\n" "$no_n"
printf "%s\n" "$ip"
curl -fIkSs https://"$ip":9002 | head -n 1
done
done
'
As the remote script would become larger and less qouting friendly, I would save it into another remote_scripts.sh and execute ssh ... -m remote_scripts.sh.
I don't get what you are trying to do with that sudo su, which 100% does not do what you want.
If the no_n magic number is the number of times to execute that curl and you have xargs and you don't really care about errors, you can just do a magic and confusing oneliner:
#!/bin/bash
set -euo pipefail
read -r host _ <webip.txt
paste serial.txt ip.txt | ssh -t -o StrictHostKeyChecking=no -p 2345 -v ubuntu#"$host" 'xargs -n2 -- sh -c "seq 0 \"\$1\" | xargs -n1 -- sh -c \"curl -fIkSs https://\\\"\\\$1\\\":9002 | head -n 1\" -- \"\$2\"" --'
Preparing all the command to run maybe actually more readable and may save some nasty qouting to resolve. But this really depends on how big serial.txt and ip.txt are and how big are the commands to be executed on the remote machine, as you want to minimize the number of bytes transferred between machines.
Here the commands to run are constructed on local machine (ie. "$(...)" is passed to ssh) and executed on remote machine:
# semi-readable script, not as fast and no xargs
ssh -t -o StrictHostKeyChecking=no -p 2345 -v ubuntu#"$host" "$(paste serial.txt ip.txt | while read -r serial ip; do
seq 0 "$serial" | while read -r _; do
echo "curl -fIkSs \"https://$ip:9002\" | head -n 1"
done
done)"
HERE-doc does not expand shell commands, so:
$ cat <<EOF
> echo 1
> EOF
echo 1
but you can use command substitution $( ... ):
$ cat <<EOF
> $(echo 1)
> EOF
1

pass variables to shell script over ssh

How do I make $1 and $2 variables to the remote shell through ssh. Below is the sample,
#!/bin/bash
user_name="${1}"
shift
user_password="${1}"
shift
tenant_name="${1}"
realscript="/IDM_ARTIFACTS/reset.sh"
ssh -qT oracle#slc05pzz.us.oracle.com bash -c "'echo $user_name'" < "$realscript"
I am able to echo $user_name but not able to access it in $realscript.
Cant call using HERE tags or single quotes'' as the script doesn't have straight forward commands.
What other options do I have? Please help
I do not have your script, so I put a test one on my remote host:
$ realscript=/home/jack/show_params.sh
$ second="second one"
$ ssh TEST cat ${realscript}
#!/bin/bash
nParams=$#
echo There are ${nParams} parameters.
for (( ii=1; ii<=${nParams}; ii++ )); do
echo "$1"
shift
done
$ ssh TEST 'bash '${realscript}' "first one" '\'${second}\'
There are 2 parameters.
first one
second one
The quoting gets a bit weird, but you can pass into parameters variables with spaces.

Execute Script available on remote machine

I am trying to execute a script available on remote machine using ssh. The output differ if it is run from client via ssh or run after ssh into the server.
The script will trim a file.
tail -n 100 users.txt > temp.txt
rm users.txt
mv temp.txt users.txt
echo $(wc -l users.txt)
echo Done
On running from client side :
client#client_mac $ ssh user#server_mac '~/path_to_script/demo_script.sh'
Output :
0 users.txt
Done
while after ssh'ing at server side :
client#client_mac $ ssh user#server_mac
user#server_mac $ cd ~/path_to_script/
user#server_mac $ ./demo_script.sh
Output :
100 users.txt
Done
How do we execute a script that is available on remote machine ? Is the syntax different ?
Your script always looks for users.txt in the current working directory.
In the first example, the current working directory is your home directory; that's why you have to run the script with ~/path_to_script/demo_script.sh rather than ./demo_script.sh. As such, you are getting the line count of ~/users.txt in your output.
In the second example, you change the working directory from ~ to ~/path_to_script before executing the script, so the output contains the line count of ~/path_to_script/users.txt.

Resources