Issues when spawn'ing ssh on expect ( {$var} vs. "$var" ) - linux

I have a expect script that so far it is working fine ... it spawn a ssh session over an existing ssh tunnel like this:
spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o {ProxyCommand=nc -X 5 -x localhost:8888 %h %p} "$user_ip"
$user_iphas the username and destination IP, as expected by ssh, like username#IP
The problem is that sometimes, port 8888 is being used by another ssh tunnel, and every time this happens I have to tweak the code and change the tunnel port.
So, I am trying to send the port in a variable, to avoid touch the code all the time.
I am getting the tunnel port from command line, as:
set proxy_port [lindex $argv 2]
and then
spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o {ProxyCommand=nc -X 5 -x localhost:"$proxy_port" %h %p} "$conn"
I see that proxy_portvariable is properly set, but when the script try to spawn the ssh, I get:
spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o {ProxyCommand=nc -X 5 -x localhost:8888 %h %p} USERID#10.0.0.1
command-line line 0: garbage at end of line; "-o".
send: spawn id exp5 not open
while executing
"send "$pwd\r""
(file "./amm-qev.new.exp" line 36)
In the error above, I see that the port was properly replaced, but it is complaining about ssh syntax.
What is wrong there that my weak eyes are not catching ?

Tcl's {...} syntax is like single-quoted string ('...') in shell where the $var would not be expanded. You should use double quotes.
spawn ssh -o UserKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=no \
-o "ProxyCommand=nc -X 5 -x localhost:$proxy_port %h %p" \
"$conn"

Related

Shell script to login to remote VM and run commands from remote VM

I need to login to a remote VM and run some commands. I am able to login successfully but echo command does not return list of files from the remote VM instead it returns output from local machine. Can anyone suggest how can I achieve this?
ssh -o IdentitiesOnly=yes -o StrictHostKeyChecking=no root#$1<<EOF
cd /var;
echo "$(ls)";
EOF
exit
It worked after removing echo. PFB solution:
ssh -o IdentitiesOnly=yes -o StrictHostKeyChecking=no root#$1 << EOT
cd /var;
ls -ltr;
EOT
exit
You have to escape $ in EOF sequence like this:
ssh -o IdentitiesOnly=yes -o StrictHostKeyChecking=no root#$1<<EOF
cd /var;
echo "\$(ls)";
EOF
Or escape whole EOF sequence like this:
ssh -o IdentitiesOnly=yes -o StrictHostKeyChecking=no root#$1<<'EOF'
cd /var;
echo "$(ls)";
EOF
alternatively, if you quote the marker, then substitution doesn't take place in the local shell:
ssh -o IdentitiesOnly=yes -o StrictHostKeyChecking=no root#$1<<'EOF'
cd /var;
echo "$(ls)";
EOF
exit

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.

Use ssh to launch remote process and exit

I am trying to use ssh from the command line to launch a python server on a remote server using the following command:
$ ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
-o ConnectTimeout=5 -f -i mykey.pem user#99.99.99.99 \
'python -m SimpleHTTPServer 3000 & echo $! > /home/user/pysrv.pid'
After the launch my ssh session goes to the background but does not exit until the python server is running. Is there a way I can setup the command so that ssh does not stick around as a background process on my current machine?
You can do
nohup python -m SimpleHTTPServer 3000 & echo $! > /home/user/pysrv.pid &
It will create a detached task that doesn't need the parent (ssh).
OTOH, if you kill the ssh server process, you won't be able to connect again. Is this what you want, or are you just trying to kill the session? If it's just the session, it should go away by itself after the connection is dropped.
The ssh command exits when the TCP connection is closed. If you redirect stdin and stderr of the remote command, nothing will be connected to the TCP connection and it will close.
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ConnectTimeout=5 -f -i mykey.pem user#99.99.99.99 'python -m SimpleHTTPServer 3000 2>/dev/null 2>&1 </dev/null& echo $! > /home/user/pysrv.pid'

Skip password prompt using sh script

I have script that inputs the list of server ips and ssh using pem key to run commands but some servers have password i want to skip that so that it take the next ip ?
Below is the script:
cat privateiptest-ss | while read LINE
do
echo $LINE >> ss-prodcht1.txt
stackname=$LINE
ssh -o "PasswordAuthentication=no" -o "StrictHostKeyChecking no" -t -t -i key.pem ec2-user#$stackname "bash -s" < sh.sh
done
If you use the option BatchMode=yes with ssh, i.e.
ssh -o "BatchMode=yes" -o "StrictHostKeyChecking=no" -t -t -i key.pem ec2-user#$stackname "bash -s" < sh.sh
then ssh will never prompt for a password. For servers that do require a password, ssh will fail.

Ksh script: How to remain in ssh and continue the script

So for my script I want to ssh into a remote host and remain in the remote host after the script ends and also have the directory changed to match the remote host when the script ends.
#!/bin/ksh
ssh -t -X mylogin#myremotemachine 'cd $HOME/bin/folder1; echo $PWD; ssh -q -X ssh mylogin#myremotemachine; cd $HOME/bin/folder2; echo $PWD'
The PWD gets changed correctly before the second ssh. The reason for the second ssh is because it ends the script in the correct remote host but it will not retain the directory change which I attempted by putting commands after it but they won't execute.
Does anyone have any ideas?
Just launch a shell at the end of the command list:
ssh -t -X mylogin#myremotemachine 'cd $HOME/bin/folder1; echo $PWD; ssh -q -X ssh mylogin#myremotemachine; cd $HOME/bin/folder2; echo $PWD; ksh'
If you want the shell to be a login one (i.e. one that reads .profile), use exec -l:
ssh -t -X mylogin#myremotemachine 'cd $HOME/bin/folder1; exec -l ksh'
If the remote server uses an old ksh release that doesn't support the exec -l builtin and if bash or ksh93 is available, here is a workaround:
ssh -t -X mylogin#myremotemachine 'cd $HOME/bin/folder1; exec bash -c "exec -l ksh"'

Resources