Getting exit code on the remote server after jump through a bastion - linux

I would like to get the exit code of my remote command.
It's normally pretty easy, but I need to execute my command through a bastion host and I don't know take that with a easy methode.
So, this is a diagram of my architecture.
PC => Bastion => remote host
I used this code to execute my command and check the return code:
ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -At ubuntu#$ip_bastion ssh -Aq -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu#$ip_server bash <<EOF
{ ${cmd} ; } 2>&1 | sed -e 's/^/$(colors_next exec)$region:$ip:$type${normal} /'
EOF
echo $?
if [[ $? -ne 0 ]]; then
error "Error during the command execution."
exit 1
fi
But, the return code is always equal 0, while my command failed (Return 255 on the final server).
Thanks for your help :)

If you are using bash, you can use the PIPESTATUS array variable to get the exit status of each element of the pipeline.
ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -At ubuntu#$ip_bastion ssh -Aq -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu#$ip_server bash <<EOF
{ ${cmd} ; } 2>&1 | sed -e 's/^/$(colors_next exec)$region:$ip:$type${normal} /'
exit "\${PIPESTATUS[0]}"
EOF
remote_exitcode=$?
echo "remote_exitcode=${remote_exitcode}"
if [[ ${remote_exitcode} -ne 0 ]]; then
error "Error during the command execution."
exit 1
fi

The echo command is hurting you. You need to capture the value of $? before echoing it, because echo will reset it to 0, assuming that the echo command is successful.
ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -At ubuntu#$ip_bastion ssh -Aq -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu#$ip_server bash <<EOF
{ ${cmd} ; } 2>&1 | sed -e 's/^/$(colors_next exec)$region:$ip:$type${normal} /'
EOF
rc=$?
echo $rc
if [[ $rc -ne 0 ]]; then
error "Error during the command execution."
exit 1
fi
Optionally, you may want to exit $rc so that your script exits with the same return code that your SSH command exited with, which might in some cases be helpful in figuring out what went wrong.

Related

How to run the bash script in parallel rather than sequentially?

#!/bin/bash
some_array=($1)
echo "-- Setting-Up VM --"
for i in ${some_array[#]}; do
echo "VM #: $i"
case "$i" in
"1")
echo "Setting-Up VM $i"
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root#10.xx.x.xx <<EOF
pwd
nohup yes | /etc/rc.d/init.d/lifconfig
su tarts
nohup yes | vncserver
sleep 10
exit
exit
EOF
;;
"2")
echo "Setting-Up VM $i"
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root#10.xx.x.xx <<EOF
pwd
nohup yes | /etc/rc.d/init.d/lifconfig
su tarts
nohup yes | vncserver
sleep 10
exit
exit
EOF
;;
"3")
echo "Setting-Up VM $i"
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root#10.xx.x.xx <<EOF
pwd
nohup yes | /etc/rc.d/init.d/lifconfig
su tarts
nohup yes | vncserver
sleep 10
exit
exit
EOF
;;
*)
echo "unknown VM!"
;;
esac
done
Can someone please guide me I have the above script which is executed when we run the script for instance ./vmSetup.sh "1 2 3" but this is executed sequentially. I had created this script but now I want to run the cases in the script i.e. 1, 2 and 3 in parallel. Can someone also tell me how to run for instance 8 cases in parallel?
Put each case ... esac statement in the background by ending it with &. Then use wait after the loop to wait for all the background processes to finish.
#!/bin/bash
some_array=($1)
echo "-- Setting-Up VM --"
for i in ${some_array[#]}; do
echo "VM #: $i"
case "$i" in
"1")
echo "Setting-Up VM $i"
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root#10.xx.x.xx <<EOF
pwd
nohup yes | /etc/rc.d/init.d/lifconfig
su tarts
nohup yes | vncserver
sleep 10
exit
exit
EOF
;;
"2")
echo "Setting-Up VM $i"
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root#10.xx.x.xx <<EOF
pwd
nohup yes | /etc/rc.d/init.d/lifconfig
su tarts
nohup yes | vncserver
sleep 10
exit
exit
EOF
;;
"3")
echo "Setting-Up VM $i"
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root#10.xx.x.xx <<EOF
pwd
nohup yes | /etc/rc.d/init.d/lifconfig
su tarts
nohup yes | vncserver
sleep 10
exit
exit
EOF
;;
*)
echo "unknown VM!"
;;
esac &
done
wait
Why do you have a case statement at all when all these are identical?
#!/bin/bash
echo "-- Setting-Up VM(s) --"
for i in "$#"; do
case "$i" in
1) IP=1.2.3.4;;
2) IP=2.2.3.4;;
3) IP=3.2.3.4;;
*) echo "Invalid option '$i'" >&2; exit 1;;
esac
echo "Setting-Up VM $i"
sshpass -p root12 ssh -tt -o StrictHostKeyChecking=no root#$IP <<EOF &
pwd
nohup yes | /etc/rc.d/init.d/lifconfig
su tarts
nohup yes | vncserver
sleep 10
exit
exit
EOF
done
To run a job in background, just use &
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root#$IP <<EOF &
It's just confusing because of the here-doc, but the & metacharacter still parses correctly on my system. Try it.
Also, rather than quoting all your options in one string and then parsing them back out to an array, why not just simplify the whole thing and let them come in as separate arguments? Call it as
./vmSetup.sh 1 2 3 # NOT "1 2 3" with quotes
and the loop becomes just
for i in "$#" # properly quoted, though wouldn't matter for 1 2 3
This whole thing seems a lot simpler and easier to maintain.
Another option, which is what I would do: create a file that is a list of the DNS/IP addresses you need, then pass that file as the lone argument.
#!/bin/bash
while read -r addr || [[ -n "$addr" ]]
do echo "Setting-Up VM $addr"
sshpass -p "root12" ssh -tt -o StrictHostKeyChecking=no root#$addr <<EOF &
pwd
nohup yes | /etc/rc.d/init.d/lifconfig
su tarts
nohup yes | vncserver
sleep 10
exit
exit
EOF
done < "$1"
Better, add valid error checking first to make sure the file exists and is readable, etc, but as a simple case, this should work.
For even better, cleaner, safer code, read https://mywiki.wooledge.org/BashFAQ/001 and follow those suggestions. :)
If ./vmSetup.sh 1 works as expected, these should work:
parallel -j8 ./vmSetup.sh {} ::: 1 2 3 ... 100
seq 100 | parallel -j8 ./vmSetup.sh

How to pass IF statement into SSH in UNIX?

I have the following bash script:
#!/bin/bash
set command "pgrep -x 'gedit' "
ssh -t test#192.168.94.139 $command
Now, I want to include this as well in the other device:
if pgrep -x "gedit" > /dev/null
then
echo "Running"
else
echo "Not Running"
fi
How can I make the IF Statement run on the other device? I wasn't able to include it in the ssh.
I tried this:
set command "pgrep -x 'gedit' "
ssh -t test#192.168.94.139 '
if pgrep -x "gedit" > /dev/null
then
echo "Running"
else
echo "Not Running"
fi'
But it didn't work! maybe because there is no command at the beginning?
Thanks.
Invoke bash with heredoc:
ssh -t test#192.168.94.139 bash <<EOF
if pgrep -x "gedit" > /dev/null
then
echo "Running"
else
echo "Not Running"
fi
EOF

bash script accessing ec2 instance

This script required an ip and the script or file that we have to run on the remote server i gave a file in which i have wrote commands like
touch /root/test
ls /root/test
this make the file but do not show and it is displaying an error
tcgetattr: Inappropriate ioctl for device
connection closed
How can I resolve this is there any suggestion ??
#!/bin/bash
# The private key used to identify this machine
IDENTITY_KEY=/home/admnew.pem
syntax()
{
echo "Syntax: Ec2.sh server_ip scriptFile]"
echo "For example: ./Ec2.sh server_ip scriptFile"
exit 1
}
if [ $# -ne 2 ]
then
echo not enough arguments
syntax
fi
echo "Running script $2 on $1"
ssh -t -t -i $IDENTITY_KEY ec2-user#$1 sudo -i 'bash -s' < $2
exit
exit
echo "Done"
Try:
ssh -t -t -i $IDENTITY_KEY ec2-user#$1 sudo -i 'bash -s' <<EOF
(
$(cat "$2")
)
EOF
e.g. wrap the script into (), e.g the:
touch /root/test
ls /root/test
should be
(
touch /root/test
ls /root/test
)

Bash Script is returning non-zero status

I'm trying to install beanstalkd on an Ubuntu 14.04 LTS system. Seems to go okay, except for the following is giving me non-zero return status. Vagrant halts once this occurs and I have other scripts to install after wards that don't run.
I've tried
grep -q "START=yes"
grep --quiet "START=yes"
grep "START=yes" > /dev/null
non seem to suppress the output of GREP
echo -n "Checking /etc/default/beanstalkd for beanstalkd startup line ... "
if [ -f /etc/default/beanstalkd ]; then
echo -n "START=yes is"
grep "START=yes" /etc/default/beanstalkd > /dev/null
if [ $? = 0 ]; then
echo -n "..already present"
else
echo -n "START=yes" >> /etc/default/beanstalkd
echo -n "..Added to /etc/default/beanstalkd"
fi
fi
echo "Done!"
Result :
==> default: Checking /etc/default/beanstalkd for beanstalkd startup line ...
==> default: START=yes is
The SSH command responded with a non-zero exit status. Vagrant
assumes that this means the command failed. The output for this command
should be in the log above. Please read the output to determine what
went wrong.
The following invocation of grep will suppress all grep output (both stderr and stdout). No warnings, no errors, nothing.
grep -q "START=yes" /etc/default/beanstalkd >/dev/null 2>&1
If your query was about the if [ $? = 0 ]; then line not working as expected, you can replace it with this:
if grep -q "START=yes" /etc/default/beanstalkd >/dev/null 2>&1; then
# already present

shell script ssh command not working

I have a small list of servers, and I am trying to add a user on each of these servers. I can ssh individually to each server and run the command.
sudo /usr/sbin/useradd -c "Arun" -d /home/amurug -e 2014-12-12 -g users -u 1470 amurug
I wrote a script to loop through the list and run this command but I get some errors.
#!/bin/bash
read -p "Enter server list: " file
if [[ $file == *linux* ]]; then
for i in `cat $file`
do
echo "creating amurug on" $i
ssh $i sudo /usr/sbin/useradd -c "Arun" -d /home/amurug -e 2014-12-12 -g users -u 1470 amurug
echo "==============================================="
sleep 5
done
fi
When I run the script it does not execute the command.
creating amurug on svr102
Usage: useradd [options] LOGIN
Options:
What is wrong with my ssh crommand in my script?
Try this script:
#!/bin/bash
read -p "Enter server list: " file
if [[ "$file" == *linux* ]]; then
while read -r server
do
echo "creating amurug on" "$server"
ssh -t -t "$server" "sudo /usr/sbin/useradd -c Arun -d /home/amurug \
-e 2014-12-12 -g users -u 1470 amurug"
echo "==============================================="
sleep 5
done < "$file"
fi
As per man bash:
-t
Force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs on a remote which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.

Resources