124

How to get parent PID from a given child's PID?

I know I can manually check it under /proc, I wonder if there is a smart/better way to achieve this in Ubuntu. Note the parent may or may not be killed.

Thanks

Kolay.Ne
  • 107
cache
  • 1,541

5 Answers5

142

How to get a parent PID (PPID) from a child's process ID (PID) using the command-line

Use ps -o ppid=

  • e.g. ps -o ppid= 2072 returns 2061, which you can easily use in a script etc. ps -o ppid= -C foo gives the PPID of process with command foo. You can also use the old fashioned ps | grep: ps -eo ppid,comm | grep '[f]oo'.
  • Fuller explanation: ps -f 2072 returns
    UID        PID  PPID  C STIME TTY      STAT   TIME CMD
    izx       2072  2061  0 07:16 ?        S      0:00 /usr/lib/pulseaudio/pulse/gconf-helper
    
  • The pstree relation is: pstree -s -p 2072:
    init(1)───pulseaudio(2061)───gconf-helper(2072)
    
Olorin
  • 3,548
ish
  • 142,198
  • Do you know of a way to make pstree show invocations (command + arguments) without splitting lines? My installation automatically splits lines if I add arguments, even if the result could easily fit on one line. The man page appears to say as much, but doesn't give a reason. My workaround involves extracting PID's from pstree and using ps -o args ... on the results, but that has a bit of a smell. – John P Mar 01 '17 at 04:13
  • Just something that surprised me: The space after ppid= but before the pid seems to be necessary. I got different results if I omitted it. – Gregory Arenius Feb 08 '19 at 00:27
  • I did ps -o ppid=$$ to get the PPID of the current shell. Thanks. – aderchox Sep 09 '20 at 18:16
  • I get multiple processes listed, when there should be only one parent process... or not? So in my opinion this solution doesn't work... – goulashsoup May 01 '24 at 07:41
51

Using only variable to get parent PID :

echo $PPID

if you need the command from this parent pid:

cat /proc/$PPID/comm

if you need the full command line (with all options):

cat /proc/$PPID/cmdline

Explanation

  • $PPID is defined by the shell, it's the PID of the parent process
  • in /proc/, you have some dirs with the PID of each processes. Then, if you cat /proc/$PPID/comm, you echo the command name of the PID

Check man proc

  • 3
    This is the best answer. procfs is a kernel API. execute a command and parse the output is a nonsense. – Massimo Apr 09 '19 at 05:28
  • 4
    This is also potentially the most portable, PPID is defined as part of the POSIX standard so any POSIX compliant shell should be setting this appropriately. See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html – RobV Apr 24 '19 at 16:37
  • Watch it, $$ and $PPID are only set when bash start. $PPID doesn't change if the parent process quits (getppid would return 1), and $$ doesn't change if you fork a function in your script. – Mathieu Longtin Jun 07 '24 at 21:40
  • WAY cleaner than ps or any other solution that has to launch a new process. Deserves to be the top answer! – LyrePyre Jun 12 '24 at 21:32
19

Using pstree by command name

Using pstree you can search by the child process name and get the Process ID (PID) along with the parents, grandparents and any children of the child process:

$ pstree -hp | grep sleep
           |-cron(763)---cron(795)---sh(839)---display-auto-br(841)---sleep(8414)

In this case sleep is the child command and it's PID is 8414. It's parent ID is 841 and is called display-auto-brightness. The grandparent is a shell (sh) with a process ID of 839. The great-grandparent is cron with a process ID of 795. The great-great-grandparent is also cron with a process ID of 763.

If you want to search by Process ID of sleep instead of name you can use:

$ pstree -hp | grep 14653
           |-cron(763)---cron(795)---sh(839)---display-auto-br(841)---sleep(14653)

Notice the sleep process ID changed to 14653. The parent (PID 841) sleeps for 1 minute, wakes up for a split second and then starts a new sleep command which gets a new process ID. This is another reason why searching for sleep is easier than searching by process ID.

This code was taken from: Automatically adjust display brightness based on sunrise and sunset and adapted to this question.


To see a nested chain all the way back to boot process use the PID instead of name:

$ pstree -aps 8541
systemd,1 splash fastboot kaslr
  └─cron,763 -f
      └─cron,795 -f
          └─sh,839 -c    /usr/local/bin/display-auto-brightness
              └─display-auto-br,841 /usr/local/bin/display-auto-brightness
                  └─sleep,8541 60

Note: Another minute has passed and the sleep command gets a new PID (8541).

  • In your example, this method wouldn't have worked for the cron process with PID 807. – Olorin Mar 06 '18 at 04:38
  • @Olorin In both examples you could grep on 807 or cron and the same line would be retruned as well as more children if spawned. But the question was about finding the parent, not all the children. – WinEunuuchs2Unix Mar 06 '18 at 05:28
  • Exactly - how do you find the parent of PID 807 with that output? You can't, becvause it doesn't include the parent of 807. – Olorin Mar 06 '18 at 06:41
  • @Olorin The parent of cron is systemd which is PID 1. I don't think you can kill PID 1. – WinEunuuchs2Unix Mar 06 '18 at 11:09
  • I didn't say anything about killing anything. Just to clarify, now you're claiming that taking the first line of pstree or grepping for the command name will always give the the parent PID? – Olorin Mar 06 '18 at 13:14
  • The OP question references parent being active / killed. The inclusion of systemd line is for from which PID 1 calls in early boot. The sleep command illustrated is actually part of working code designed to wake parent on system resume. I found this method easier than dealing with searching by PID and wanted to share with others. – WinEunuuchs2Unix Mar 06 '18 at 13:20
  • Ok... "The inclusion of systemd line is for from which PID 1 calls in early boot." Couldn't make sense of that. Not sure what the rest has to do with anything I said, but sure. – Olorin Mar 06 '18 at 15:04
  • @Olorin Sorry I was typing on my cell phone. The change I made was to reveal the parent of cron which is systemd running on PID 1. In other cases you can include the line 1 above the grep search string with -B 1 parameter.. The spirit of the answer is to show how much easier and intuitive pstree and grepping on command name can be. – WinEunuuchs2Unix Mar 07 '18 at 00:24
  • Nope... -B1 won't cut it either: https://paste.ubuntu.com/p/BnfQBMSPbM/ I don't know how useful this answer is if the letter of it doesn't work, whatever be the spirit... and clearly the spirit of it isn't correct either, since getting the PPID from pstree output is not easy or intuitive just by grepping. – Olorin Mar 07 '18 at 01:33
  • @Olorin In your case you do need to use the PID, ie: $ pstree -ps 1911 results in: systemd(1)───lightdm(1012)───lightdm(1555)───upstart(1821)───window-stack-br(1911). This was stated in izx's answer above though. – WinEunuuchs2Unix Mar 07 '18 at 03:00
  • Exactly. Either the suggestions don't work well, or are already in another answer. – Olorin Mar 07 '18 at 03:31
  • Even with process name, ps -o ppid -C sleep is far better than this hit and miss answer. – Olorin Mar 07 '18 at 03:33
  • I think this is an excellent answer. Providing the entire lineage of ancestors comes in quite handy - esp. for those (like me) who don't wish to immerse themselves in all of the arcanery surrounding ps. For example, piping the output to grep allows a script to determine if it was started by cron or an interactive shell: pstree -aps $(echo $$) | grep -m 1 "[c]ron," – Seamus Jan 21 '25 at 00:18
10

ps -efj can also be used for the same.

For example,

> ps -efj | head
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root         1     0     1     1  0 Jul01 ?        00:00:13 /sbin/init splash
root         2     0     0     0  0 Jul01 ?        00:00:00 [kthreadd]
root         3     2     0     0  0 Jul01 ?        00:00:02 [ksoftirqd/0]
root         5     2     0     0  0 Jul01 ?        00:00:00 [kworker/0:0H]
root         7     2     0     0  0 Jul01 ?        00:06:44 [rcu_sched]
root         8     2     0     0  0 Jul01 ?        00:00:00 [rcu_bh]
root         9     2     0     0  0 Jul01 ?        00:00:00 [migration/0]
root        10     2     0     0  0 Jul01 ?        00:00:08 [watchdog/0]
root        11     2     0     0  0 Jul01 ?        00:00:08 [watchdog/1]
Pallav Jha
  • 223
  • 2
  • 8
1

If you want id of the process that launched your shell, just use environment variable PPID. For example

echo $PPID

If you have a process id without any relation to your current shell, you can get the parent id (in environment variable PID with one of the following commands:

awk '{print $4}' < /proc/$PID/stat
ps -o "ppid=" $PID
read ignore ignore ignore PARENT_PID ignore < /proc/$PID/stat ; echo $PARENT_PID

The last one can be executed without creating a new process but it pollutes the environment with new variabled called ignore in addition to setting $PARENT_PID to correct value.