简体   繁体   中英

Error when stacking SSH command arguments within a bash script using other scripts as variables

I have a csv file called addresses.csv which looks like this,

node-1,xx.xxx.xx.xx,us-central-a
....
node-9,xxx.xx.xxx.xx,us-east1-a

I have a script below called 0run.sh,

#!/bin/bash
username='user'
persist="bash /home/${username}/Documents/scripts/disk/persistentDisk.sh"
first="bash /home/${username}/Documents/scripts/disk/firstAttach.sh"

while IFS=, read -r int ip <&3; do
  if [ "$int" == "node-1" ]; then
--->ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l ${username} ${ip} "${persist}; ${first}"<---
  else
    ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l ${username} ${ip} "${first}"
  fi
done 3<addresses.csv

The error occurs in the part of the code where I drew the arrows.

When it runs on node-1 , instead of running ..persistentDisk.sh followed by ..firstAttach.sh , it only runs ..persistentDisk.sh and gives me the following error before it runs ..persistentDisk .

bash: /home/user/Documents/scripts/disk/firstAttach.sh: No such file or directory

The rest of the script runs completely fine. The only error occurs at this one part where it misses the 2nd script.

When I run the command like this it runs fine.

ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l ${username} ${ext} "${first}"

When I run it like this, it runs fine as well.

ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l user xxx.xx.xxx.xx "bash /home/${username}/Documents/scripts/disk/persistentDisk.sh; bash /home/${username}/Documents/scripts/disk/firstAttach.sh"

When I run the command like with a \ before the ;to escape it like this,

ssh -i ~/.ssh/key -o StrictHostKeyChecking=no -l ${username} ${ext} "${persist}\; ${first}"

I get the following error, and neither scripts run within the node-1 part of the code, but the rest of the code's else loops run fine.

bash: /home/user/Documents/scripts/disk/persistentDisk.sh;: No such file or directory

Why can't I stack the 2 commands within the if statement in the ssh using variables?

If I clearly understand: your real problem consist to leave STDIN free for interaction in target host!

About read and redirection

Try using:

#!/bin/bash
username='user'
persist="bash /home/${username}/Documents/scripts/disk/persistentDisk.sh"
first="bash /home/${username}/Documents/scripts/disk/firstAttach.sh"

while IFS=, read -r -u $list int ip foo; do
  if [ "$int" == "node-1" ]; then
       echo CMD... $ip, $persist
  else
       [ "$ip" ] && echo CMD... $ip, $first
  fi
done {list}<addresses.csv

Tested, this èroduce:

CMD... xx.xxx.xx.xx, bash /home/user/Documents/scripts/disk/persistentDisk.sh
CMD... xxx.xx.xxx.xx, bash /home/user/Documents/scripts/disk/firstAttach.sh
  • -u flag to read, tell to use file descriptor ${list} instead of STDIN
  • foo is some useless variable used to prevent rest of line to be stored in $ip ( xx.xxx.xx.xx,us-central-a in this case)
  • {list}</path/to/filename create a new variable by finding any free file descriptor .

About ssh (and redirection)

You could use:

#!/bin/bash
username='user'
persist="/home/${username}/Documents/scripts/disk/persistentDisk.sh"
first="/home/${username}/Documents/scripts/disk/firstAttach.sh"

while IFS=, read -r -u $list int ip foo; do
  [ "$int" = "node-1" ] && cmd=persist || cmd=first
  [ "$ip" ] && ssh -i ~/.ssh/key -t -o StrictHostKeyChecking=no \
                   -l ${username} ${ext} /bin/bash "${!cmd}"
  done {list}<addresses.csv

By using this syntax, you will keep STDIN free for script running on target host.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM