I am using the following code to launch a command on another machine:
#!/bin/bash
/usr/bin/rsh -n $Host_Name "cat asdf.txt &"
And I am trying to obtain the PID of the cat command by using the following:
/usr/bin/rsh -n $Host_Name pid="$!"
But when I echo $pid, it is just blank. What am I doing incorrectly? Is there an easier way of obtaining the PID of the last command that was executed on a different machine?
Thanks
You can only get the $! of the backgrounded command in the shell in which you started the command. If your command doesn't output anything to stderr, this could work:
/usr/bin/rsh -n $Host_Name "cat asdf.txt & echo $! >&2" 2> pidfile
The pid of the started command will then be stored locally in 'pidfile'.
Just a side-note: I would never use rsh. It is inherently insecure. I'd use ssh instead ;)
Related
I run the this command
$(while true;do echo Something && sleep 0.01; done;) | cat
Now I can not exit by Ctrl+C or background it by Ctrl+Z, and ps aux can't tell me which bash it is.How can I quit that bash ?
EDIT
I narrow donw the pid by find the cwd pgrep bash| (while read -r line; do lsof -p $line|grep cwd|grep EXPECTED_CWD && echo "GOT $line"; done;),finally kill that process.There is easier way to find that, but no /proc on mac.
Closing the terminal can help.
If you are using CLI-only os then you can switch to different terminal using Ctrl + Alt + F1 keys.
There you can use who or ps commands to get process-id and kill it.
ps -ef will list all processes.
you can kill second last bash process, as that will be the last command that you executed.
Note : process id assignment in linux is always greater than old one.
you're able to execute your commands with & symbol in the end of the command to run this command in background
In your case command looks like:
$(while true;do echo Something && sleep 0.01; done;) | cat &
It will show the process ID, and you'll be able to kill it, when you want
When I do the following, then I have to press CTRL-c afterwards or the shell acts weird. Left/right arrows keys e.g. doesn't move correctly and the text is messed up.
# read -r pid < <(ssh 10.10.10.46 'sleep 50 & echo $!') ; echo $pid
2135
# Killed by signal 2.
^C
#
I need this for a script, so I'd like to know why CTRL-c is needed and is it possible to work around it?
Update
It looks like it opens an extra Bash shell, and that is the one that needs to be exited.
The command I am actually interesting in is
read -r pid < <(ssh 10.10.10.46 "mbuffer -4 -v 0 -q -I 8023 > /tmp/mtest & echo $!"); echo $pid
Try this instead:
read -r pid \
< <(ssh 10.10.10.46 'nohup mbuffer >/tmp/mtest </dev/null 2>/tmp/mtest.err & echo $!')
Three important changes:
Use of nohup (you could also get a similar effect with the bash built-in disown)
Redirection of stdin and stderr to files (preventing them from holding handles that connect, eventually, to your terminal).
Use of single quotes for the remote command (with double-quotes, expansions happen before ssh is started, so the $! you get is the PID of the most recently started local background process).
I have a script to process records in some files, it usually takes 1-2 hours. When it's running, it prints a progress of number of records processed.
Now, what I want to do is: when it's running with nohup, I don't want it to print the progress; it should print progress only when it run manually.
My question is how do I know if a bash script is running with nohup?
Suppose the command is nohup myscript.sh &. In the script, how do I get the nohup from command line? I tried to use $0, but it gives myscript.sh.
Checking for file redirections is not robust, since nohup can be (and often is) used in scripts where stdin, stdout and/or stderr are already explicitly redirected.
Aside from these redirections, the only thing nohup does is ignore the SIGHUP signal (thanks to Blrfl for the link.)
So, really what we're asking for is a way to detect if SIGHUP is being ignored. In linux, the signal ignore mask is exposed in /proc/$PID/status, in the least-significant bit of the SigIgn hex string.
Provided we know the pid of the bash script we want to check, we can use egrep. Here I see if the current shell is ignoring SIGHUP (i.e. is "nohuppy"):
$ egrep -q "SigIgn:\s.{15}[13579bdf]" /proc/$$/status && echo nohuppy || echo normal
normal
$ nohup bash -c 'egrep -q "SigIgn:\s.{15}[13579bdf]" /proc/$$/status && echo nohuppy || echo normal'; cat nohup.out
nohup: ignoring input and appending output to `nohup.out'
nohuppy
You could check if STDOUT is associated with a terminal:
[ -t 1 ]
You can either check if the parent pid is 1:
if [ $PPID -eq 1 ] ; then
echo "Parent pid=1 (runing via nohup)"
else
echo "Parent pid<>1 (NOT running via nohup)"
fi
or if your script ignores the SIGHUP signal (see https://stackoverflow.com/a/35638712/1011025):
if egrep -q "SigIgn:\s.{15}[13579bdf]" /proc/$$/status ; then
echo "Ignores SIGHUP (runing via nohup)"
else
echo "Doesn't ignore SIGHUP (NOT running via nohup)"
fi
One way, but not really portable would be to do a readlink on /proc/$$/fd/1 and test if it ends with nohup.out.
Assuming you are on the pts0 terminal (not really relevant, just to be able to show the result):
#!/bin/bash
if [[ $(readlink /proc/$$/fd/1) =~ nohup.out$ ]]; then
echo "Running under hup" >> /dev/pts/0
fi
But the traditional approach to such problems is to test if the output is a terminal:
[ -t 1 ]
Thank you guys. Check STDOUT is a good idea. I just find another way to do it. That is to test tty.
test tty -s check its return code. If it's 0 , then it's running on a terminal; if it's 1 then it's running with nohup.
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"'
Script which executes commands in infinite loop in background
<SOMETHING ELSE AT START OF SCRIPT>
cmd='while true;
do
ps aux | head;
sleep 1;
done > $FILE'
ssh root#$SERVER $cmd &
...
...
<SOME OTHER TASKS>
...
...
( at the end of this script, how to kill the above snippet executing in remote server)
[ kindly note i dont want to wait as the while loop is infinite ]
Read and tried some posts from stackoverflow, but could not find exact solution for this problem.
Rather than an infinite loop, use a sentinel file:
cmd='while [ -r /tmp/somefile];
do
# stuff
done > $FILE'
ssh root#$SERVER touch /tmp/somefile
ssh root#$SERVER $cmd &
# do other stuff
ssh root#$SERVER rm -f /tmp/somefile
This follows your current practice of putting the remote command in a variable, but the arguments against that cited elsewhere should be considered.
If you want to kill the ssh process running in background at the end of your script, just do:
kill $!
I assume this is the only (or the last) process you started in background.
Try following sequence
CTRL+Z
fg
CTRL+C
or
jobs
kill %jobspec
To kill everything belonging to user logged in you could try:
whois=`w|grep $user|awk '{print $2}'`;user=root; ssh $user#server -C "ps auwx|grep $whois|awk '{print \$2}'"
This will list all the processes owned by the user you just logged in as - just add |xargs kill -9
whois=`w|grep $user|awk '{print $2}'`;user=root; ssh $user#server -C "ps auwx|grep $whois|awk '{print \$2}'|xargs kill -9 "
whois=`w|grep $user|awk '{print $2}'`;user=root; ssh $user#server -C "ps auwx|grep $whois|awk '{print \$2}'|awk '{print "kill -9 " $1}'|/bin/sh "