Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get pid of piped command?

Tags:

bash

(or How to kill the child process)?

inotifywait -mqr --format '%w %f %e' $feedDir | while read dir file event
do
#something
done &

echo $! #5431

ps eg:

 >$ ps
  PID TTY          TIME CMD
 2867 pts/3    00:00:02 bash
 5430 pts/3    00:00:00 inotifywait
 5431 pts/3    00:00:00 bash
 5454 pts/3    00:00:00 ps

It seems if I kill 5431 then 5430 (inotifywait) will be left running, but if I kill 5430 then both processes die. I don't suppose I can reliably assume that the pid of inotifywait will always be 1 less than $!?

like image 252
andrew Avatar asked May 12 '14 18:05

andrew


People also ask

Which command can show the PID?

The ps command displays information about a selection of the active processes which includes the process ID (pid=PID), terminal associated with the process (tname=TTY), cumulated CPU time in [DD-]hh:mm:ss format (time=TIME), and executable name (ucmd=CMD). Output is unsorted by default.

What is PID command in Linux?

As Linux users, we're familiar with process identifiers (PID). PID is the operating system's unique identifier for active programs that are running. A simple command to view the running processes shows that the init process is the owner of PID 1.


1 Answers

When we run a pipe, each command is executed in a separated process. The interpreter waits for the last one but if we use ampersand (&).

cmd1 | cmd2 &

The pid of processes will be probably close, but we cannot assume it reliably. In the case where the last command is a bash reserved word as while, it creates a dedicated bash (that's why your 'dir', 'file' variables won't exist after the done keyword). Example:

ps # shows one bash process
echo "azerty" | while read line; do ps; done # shows one more bash

When the first command exits, the second one will terminate because the read on the pipe return EOF. When the second command exits, the first command will be terminated by the signal SIGPIPE (write on a pipe with no reader) when it tries to write to the pipe. But if the command waits indefinitely... it is not terminated.

echo "$!" prints the pid of the last command executed in background. In your case, the bash process that is executing the while loop.

You can find the pid of "inotifywait" with the following syntax. But it's uggly:

(inotifywait ... & echo "$!">inotifywait.pid) | \
while read dir file event
do
    #something
done &
cat inotifywait.pid # prints pid of inotifywait

If you don't want the pid, but just be sure the process will be terminated, you can use the -t option of inotifywait:

(while true; do inotifywait -t 10 ...; done)| \
while read dir file event
do
    #something
done &
kill "$!" # kill the while loop

None of this solution are nice. What is your real achievement? Maybe we can find a more elegant solution.

like image 159
mcoolive Avatar answered Sep 27 '22 23:09

mcoolive