15

Can any one tell me how to get the PID of a command executed in bash.

E.g. I have a bash script that runs imapsync.

When the script is killed the imapsync process does not always get killed, so I'd like to be able to identify the PID of imapsync programatically from my script, so that I can kill the imapsync process myself in a signal handler.

So how do I programatically get the PID of a child process from a parent bash script?

Dave M
  • 4,494
  • 21
  • 30
  • 30
Jason Tan
  • 2,742
  • 2
  • 17
  • 24
  • 1
    How about "pidof imapsync"? What's wrong with it? – pitr Jan 14 '11 at 12:17
  • 2
    I did not know about pidof. However now that I do, it is not useful for this scenario as far as I can tell, because pidof seems to return all proccesses of the given command on a system - even those owned by other scripts/users. In addition imapsync is actually a perl script, so I would be doing a pidof perl, which again is likely to return processes that are not imapsync and may belong to other users. – Jason Tan Jan 14 '11 at 12:29
  • Javier is correct. This page will offer more information regarding [ProcessManagement](http://mywiki.wooledge.org/ProcessManagement). – sinping Jan 14 '11 at 15:10

4 Answers4

46
any_command args &
my_child_PID=$!

IOW, just like $$ holds your PID, $! has the PID of the most recently executed background command.

Javier
  • 9,078
  • 2
  • 23
  • 24
  • Thanks, but imapsync is not backgrounded and $! is not set if I echo it on the next line after the imapsync invocation or the first line of the signal handler. :-( – Jason Tan Jan 14 '11 at 12:37
  • 6
    if it forks and backgrounds the child, it's the parent's responsibility to save the child's PID somewhere. usual practice is saving it somewhere like `/var/run/whatever.pid`. Maybe there's a command-line option to ask it to save the PID somewhere; if not, that sounds like a feature to ask the author, or implement yourself. – Javier Jan 14 '11 at 12:51
  • 1
    Emphasis on **backgrounded**. If no process has been placed into the background (i.e., with appended `&`), then the `$!` variable is undefined. – Trevor Aug 14 '14 at 15:16
  • 1
    More similar solutions are suggested in (an answer to) [How to get pid of just started process](http://serverfault.com/a/205563/68972); as an addition to this answer, a comment there says: oh, and the "oneliner": `/bin/sh -c 'echo $$>/tmp/my.pid && exec program args' &` – sysfault Nov 24 '10 at 14:28 – imz -- Ivan Zakharyaschev Jun 02 '15 at 14:36
10

Unlike pidof, pgrep can be given a variety of options to restrict which processes it returns PIDs for. One that may be particularly useful is to select based on PPID using the PID of the current process.

pgrep -P $$ imapsync

which will only output PIDs of imapsync if they are children of your script.

Dennis Williamson
  • 60,515
  • 14
  • 113
  • 148
4

imapsync has an option to set where its pid is written:

--pidfile : the file where imapsync pid is written.

  • FYI this does not really answer my question in a general sense, but I did discover the --pidfile arg and with some faffing around it has been good enough so far.. – Jason Tan Feb 08 '11 at 14:56
  • @JasonTan why teach a man to fish, when you can give him a tasty pre-cooked fillet, so he comes back and nags you for more, tomorrow, eh? sorry for the old post, but why accept this answer over Javiers's ? – unsynchronized May 16 '16 at 13:38
0

How about putting imapsync in the background momentarily, getting the PID and then foregrounding it... Something like this:

imapsync &
pid=$!
wait $pid
retVal=$?
Mark
  • 1