Get the pid of a command whose output is piped - linux

In order to remotely start a program, log its output and immediately see that log, I'm using this script:
nohup mycommand 2>&1 | tee -a server.log &
Now, I would like to store in a file the pid of the newly started mycommand (whose name is very generic, I can't just use pgrep as there would be a risk of collision).
If I just add echo $! > mycommand.pid I get the pid of tee.
How can I reliably write the pid of mycommand to a file ?
And by the way, why doesn't this give the right pid ?
( nohup mycommand 2>&1 ; echo $! > mycommand.pid ) | tee -a server.log &

OK, this simple variant works :
( nohup mycommand 2>&1 & echo $! > mycommand.pid ) | tee -a server.log &
I'm not sure why the ; didn't work and why I have to use & instead.

Related

I want to output "<PID> Killed ~" to logfile when it kill -9 <PID>

I want to output this message /usr/local/ex1.sh: line xxx: <PID> Killed ex2.sh >> $LOG_FILE 2>&1 to logfile.
however
The "ex1.sh" output /usr/local/ex1.sh: line xxx: <PID> Killed ex2.sh >> $LOG_FILE 2>&1 to console when I executed ex1.sh in console.
The result that i want is that "ex1.sh" output to file, not that output to console.
This source is "ex1.sh".
ex2.sh >> $LOG_FILE 2>&1 &
PID=`ps -ef | grep ex2.sh | grep -v grep | gawk '{print $2}'`
/bin/kill -9 $PID >> $LOG_FILE 2>&1 &
Why does "ex1.sh" output this message to console?
The reason is that message '/usr/local/ex1.sh: line xxx: <PID> Killed ex2.sh >> $LOG_FILE 2>&1 is given by bash shell, not by kill command.
So if you redirect kill command output to a file, you will not get the message in the file.
If running like ./ex1.sh >> $LOG_FILE 2&>1, the message will be in the log file. Because ./ex1.sh forks a new bash process, the bash process will give out the message.
The output is in fact not written by the kill command or ex2.sh. It is written by the shell executing the background process ex2.sh.
The shell executing the script started the script ex2.sh in the background as a child process and is monitoring it. When the script is killed, the shell acts on this by printing the message.
In your special case the shell knows more about the killed process and the process executing kill. So it prints a rather verbose message.
If you start ex2.sh (without '&') in terminal 1 and kill it from terminal 2, the shell in terminal 1 will just print "Killed".

How to assign to a bash variable an ssh remote command the pid while capturing its

Introduction
My question is very similar to this one, except that I'd like the output from the command to be redirected to a local file instead of a remote one.
The questioner was asking for a way to retrieve the process ID with a command similar to this one, where the mbuffer command wouldn't cause hanging:
read -r pid < <(ssh 10.10.10.46 "mbuffer -4 -v 0 -q -I 8023 > /tmp/mtest & echo $!"); echo $pid
The answerer responded with the following command to resolve the problem
read -r pid \
< <(ssh 10.10.10.46 'nohup mbuffer >/tmp/mtest </dev/null 2>/tmp/mtest.err & echo $!')
Which is really helpful but still places files on the remote machine, not the local one.
My Attempts
The following is my attempt to capture a log of the output of $command:
read -r PID < <(ssh $remote 'nohup $command >&2 & echo $!' 2> $log)
Which sets PID to the process ID properly but doesn't produce a log.
Question
How can I capture a log on my local machine of the stdout of my $command while still assigning PID to the process ID of $command?
Another approach:
{ read -r pid;
# Do whatever you want with $pid of the process on remote machine
cat > my_local_system_log_file
} <(ssh 10.10.10.46 "mkfifo /tmp/mtest; mbuffer -4 -v 0 -q -I 8023 &> /tmp/mtest & echo $!; cat /tmp/mtest");
Basically, the first line is PID & further lines are logs from the process.

why nohup does not launch my script?

Here is my script.sh
for ((i=1; i<=400000; i++))
do
echo "loop $i"
echo
numberps=`ps -ef | grep php | wc -l`;
echo $numberps
if [ $numberps -lt 110 ]
then
php5 script.php &
sleep 0.25
else
echo too much process
sleep 0.5
fi
done
When I launch it with:
./script.sh > /dev/null 2>/dev/null &
that works except when I logout from SSH and login again, I cannot stop the script with kill%1 and jobs -l is empty
When I try to launch it with
nohup ./script.sh &
It just ouputs
nohup: ignoring input and appending output to `nohup.out'
but no php5 are running: nohup has no effect at all
I have 2 aleternatives to solve my problem:
1) ./script.sh > /dev/null 2>/dev/null &
If I logout from SSH and login again, How can I delete this job ?
or
2) How to make nohup run correctly ?
Any idea ?
nohup is not supposed to allow you to use jobs -l or kill %1 to kill jobs after logging out and in again.
Instead, you can
Run the script in the foreground in a GNU Screen or tmux session, which lets you log out, log in, reattach and continue the same session.
killall script.sh to kill all running instances of script.sh running on the server.

How to run nohup and write its pid file in a single bash statement

I want to run my script in background and then write its pid file. I am using nohup to do this.
This is what i came up with,
nohup ./myprogram.sh > /dev/null 2>&1 & && echo $! > run.pid
But this gives a syntax error.
The following doesn't give syntax error but the problem is echo $! doesn't write the correct pid since nohup is run in a sub shell
(nohup ./myprogram.sh > /dev/null 2>&1 &) && echo $! > run.pid
Any solutions for this, given i want a single line statement for achieving this?
You already have one ampersand after the redirect which puts your script in background. Therefore you only need to type the desired command after that ampersand, not prefixed by anything else:
nohup ./myprogram.sh > /dev/null 2>&1 & echo $! > run.pid
This should work:
nohup ./myprogram.sh > /dev/null 2>&1 &
echo $! > run.pid
Grigor's answer is correct, but not complete.
Getting the pid directly from the nohup command is not the same as getting the pid of your own process.
running ps -ef:
root 31885 27974 0 12:36 pts/2 00:00:00 sudo nohup ./myprogram.sh
root 31886 31885 25 12:36 pts/2 00:01:39 /path/to/myprogram.sh
To get the pid of your own process, you can use:
nohup ./myprogram.sh > /dev/null 2>&1 & echo $! > run.pid
# allow for a moment to pass
cat run.pid | pgrep -P $!
Note that if you try to run the second command immediately after nohup, the child process will not exist yet.

in a sh script, get the pid of a background process

Is it possible to know the pid of the iwevent process in the following bash script:
#!/bin/sh
( iwevent | logger -t IWEVENT ) &
echo the pid is: ???
Note that iwevent run until ctrl-c signal.
FYI.
I run this script in a /etc/network/interfaces "up" statement and I want to kill the running iwevent process in the related "down" statement. My aim is to log wireless events.
Something like this should do the trick:
#!/bin/sh
( { iwevent & printf "The pid is %s\n" $! >&3; } | logger -t IWEVENT ) 3>&1 &
If you need it in a variable, read the output of the above.
check "pidof" function
see this http://en.wikipedia.org/wiki/Pidof
and check the man page: man pidof

Resources