Getting exit code from SSH command running in background in Linux (Ksh script) - linux

I trying to run few commands to be executed in parallel in couple of remote servers using SSH and i need to get the correct exit code from those commands but with no success.
I am using the command below
(ssh -o LogLevel=Error "remote_server1" -n " . ~/.profile 1>&- 2>&-;echo "success" 2>&1 > /dev/null" ) & echo $? > /tmp/test1.txt
(ssh -o LogLevel=Error "remote_server2" -n " . ~/.profile 1>&- 2>&-;caname 2>&1 > /dev/null" ) & echo $? > /tmp/test2.txt
The result is always "0" (echo $?) even i forced to failed like the second example above. Any idea?

Related

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

SSH Remote command exit code

I know there are lots of discussions about it but i need you help with ssh remote command exit codes. I have that code:
(scan is a script which scans for viruses in the given file)
for i in $FILES
do
RET_CODE=$(ssh $SSH_OPT $HOST "scan $i; echo $?")
if [ $? -eq 0 ]; then
SOME_CODE
The scan works and it returns either 0 or (1 for errors) or 2 if a virus is found. But somehow my return code is always 0. Even, if i scan a virus.
Here is set -x output:
++ ssh -i /home/USER/.ssh/id host 'scan Downloads/eicar.com; echo 0'
+ RET_CODE='File Downloads/eicar.com: VIRUS: Virus found.
code of the Eicar-Test-Signature virus
0'
Here is the Output if i run those commands on the "remote" machine without ssh:
[user#ws ~]$ scan eicar.com; echo $?
File eicar.com: VIRUS: Virus found.
code of the Eicar-Test-Signature virus
2
I just want to have the return Code, i dont need all the other output of scan.
!UPDATE!
It seems like, echo is the problem.
The reason your ssh is always returning 0 is because the final echo command is always succeeding! If you want to get the return code from scan, either remove the echo or assign it to a variable and use exit. On my system:
$ ssh host 'false'
$ echo $?
1
$ ssh host 'false; echo $?'
1
$ echo $?
0
$ ssh host 'false; ret=$?; echo $ret; exit $ret'
1
$ echo $?
1
ssh returns the exit status of the entire pipeline that it runs - in this case, that's the exit status of echo $?.
What you want to do is simply use the ssh result directly (since you say that you don't want any of the output):
for i in $FILES
do
if ssh $SSH_OPT $HOST "scan $i >/dev/lull 2>&1"
then
SOME_CODE
If you really feel you must print the return code, that you can do that without affecting the overall result by using an EXIT trap:
for i in $FILES
do
if ssh $SSH_OPT $HOST "trap 'echo \$?' EXIT; scan $i >/dev/lull 2>&1"
then
SOME_CODE
Demo:
$ ssh $host "trap 'echo \$?' EXIT; true"; echo $?
0
0
$ ssh $host "trap 'echo \$?' EXIT; false"; echo $?
1
1
BTW, I recommend you avoid uppercase variable names in your scripts - those are normally used for environment variables that change the behaviour of programs.

get return value of command run with script -c

Is there a way to capture the return value of a program run using script -c?
For example (in bash)
/bin/false; echo $? # outputs 1
/usr/bin/script -c "/bin/false" /dev/null; echo $?
# outputs 0 as script exited successfully.
I need to get the return value from /bin/false instead of from /usr/bin/script.. is this possible? I'm using script to trick a program into thinking it is running in a real tty even though it isn't... Thanks!
According to man script, using -e option will return the exit code of the child process.
-e, --return
Return the exit code of the child process.
Uses the same format as bash termination
on signal termination exit code is 128+n.
Here's some example.
$ /usr/bin/script -e -c "/bin/false" /dev/null; echo $?
1
$ /usr/bin/script -e -c "/bin/true" /dev/null; echo $?
0
$ /usr/bin/script -e -c "exit 123" /dev/null; echo $?
123

Bash: start remote python application through ssh and get its PID

I'm creating a little bash script to copy new files from a windows machine to a remote linux centos server (i run this script using the git-shell) then i want to restart the python application thats running in the server to use those new files.
The problem is that everytime i run this script i want to end the actual running process before i start it again, so i want to get the pid of the process i start and save it to a file in the remote host so i can read it from there the next time i run the program and kill it.
My code by now looks similar to this:
echo "Copying code files to server..."
# The destination folder has to exist in the server
scp -r ./python/ root#myserver:/root/
echo "Checking for running processes..."
if ssh root#myserver 'ls dmr.pid >/dev/null'; then
echo "PID file exists, reading file..."
PID=$(ssh root#myserver 'cat dmr.pid')
# Terminate the actual process
echo "Terminating the process with PID '$PID'..."
ssh root#myserver 'kill $PID'
else
echo "PID file doesn't exist, not known processes running"
fi
# Restart the server and get the PID
echo "Restarting the server..."
ssh root#myserver 'python /root/python/run_dev_server.py > /dev/null 2>&1 &'
SERV_PID=$(ssh root#myserver 'echo $!')
echo "Saving PID to file dmr.pid"
ssh root#myserver "echo '$SERV_PID' > \"dmr.pid\""
echo "Sucesfully finished!"
The important lines are:
ssh root#myserver 'python /root/python/run_dev_server.py > /dev/null 2>&1 &'
SERV_PID=$(ssh root#myserver 'echo $!')
the problem with this is that the script finishes but the file ends up empty as well as the $SERV_PID variable.
And if i dont redirect the outputs and just do something like this:
SERV_PID=$(ssh root#myserver 'python /root/python/run_dev_server.py & echo $!')
i get stuck after "Restarting the server" and never get the PID or the file that will contain it or even the end of the script.
But if i run this right in the console:
ssh root#myserver 'python /root/python/run_dev_server.py & echo $!'
i get a PID printed to the terminal.
Any advice on this would be really appreciated.
ssh root#myserver 'python /root/python/run_dev_server.py > /dev/null 2>&1 &'
SERV_PID=$(ssh root#myserver 'echo $!')
With the above code, you are running two ssh commands and the both create two different shells. The problem is echo $! gives the most recent background process' ID from the current shell which is none.
That is, when you ssh for the second time, it's new shell and there's no background process running in it and hence echo $! gives no output. This explains why your PID file is empty.
Instead what you can do is to lookup for all instances of your python script and kill them using killall command. Or similar idea using ps command.
Thanks to Kingslndian i solved it by making one single command that did the three steps i required, so with that avoided the problem of running in different shells:
ssh root#myserver 'python /root/python/run_dev_server.py > /dev/null 2>&1 & echo $! > "dmr.pid"'

How to output return code in shell?

I'm trying to call a custom shell script through sh:
/bin/sh -c 'myscript.sh` >log.txt 2>&1 & echo $!
Output of this command is a PID of a created background process. I want to instruct /bin/sh to save return code of myscript.sh to some file. Is it possible?
echo $? >> /path/to/return_code
$? has the return code of the last statement in bash.
(/bin/sh -c "myscript.sh" >log.txt 2>&1 ; echo $? >somefile) & echo $!
(
/bin/sh -c 'myscript.sh` >log.txt 2>&1
echo $? > some_file
) &

Resources