3

I'm looking for a way to get the PID of a short child process in Linux. The process is instant from a human perspective. I know the parent process which will spawn the child process.

Is there a way to log information about all the processes that are created by a specific parent process?

I'm not looking for a way to retroactively figure out the PID of the child but a way to log it once it happens.

  • 1
    I think it would be a good idea if you fleshed out the context a little further -- at what point, and where, do you want to the pid? From within the parent, when the child starts? Completely externally, after the process has finished? – goldilocks Jul 15 '13 at 13:47
  • I just want the id the (child) process had while it was running and the only thing i know about the process is who will be its parent. Why would it change its id during execution? – TheMeaningfulEngineer Jul 15 '13 at 13:55
  • Sorry, I did not at all mean the pid would be different at different points in time. A) It is easy to get the pid in the parent when the child is created. B) However, if no record has been kept, then it would be impossible (AFAIK) to get it externally after the process has exited (it might also be considered meaningless, but no doubt you have your reasons). Ie, if you can't get it at the time (from the process itself, or the parent, or by closely monitoring the system) then you are out of luck. – goldilocks Jul 15 '13 at 14:04
  • Ok, i understand what you mean, will update the question :) – TheMeaningfulEngineer Jul 15 '13 at 14:07
  • Related: How to get environmental variables of a very short process? (most solutions to one also solve the other) – Gilles Jul 15 '13 at 21:38
2

You could use the audit system:

sudo auditctl -a exit,always -S execve -F ppid="$pid"

would cause audit entries to be generated each time a child of $pid executes a command. audit.log would have things like:

type=SYSCALL msg=audit(1373986729.977:377): arch=c000003e syscall=59 success=yes exit=0 a0=7ff000e4b188 a1=7ff000e4b1b0 a2=7fff928d47e8 a3=7fff928caac0 items=2 ppid=7502 pid=691 auid=10031 uid=10031 gid=10031 euid=10031 suid=10031 fsuid=10031 egid=10031 sgid=10031 fsgid=10031 ses=1 tty=pts5 comm="echo" exe="/bin/echo" key=(null)
type=EXECVE msg=audit(1373986729.977:377): argc=2 a0="/bin/echo" a1="test"
type=CWD msg=audit(1373986729.977:377):  cwd="/tmp"
type=PATH msg=audit(1373986729.977:377): item=0 name="/bin/echo" inode=131750 dev=fe:00 mode=0100755 ouid=0 ogid=0 rdev=00:00

Where you can find the pid amongst other things.

If you're interested in processes that don't necessarily execute something, you can add audit rules for the fork and clone system calls.

2

[this answer ispired by this ams aswer ]

If the child process is a distinct executable (lets call it foo ) , you can try to use a shell wrapper.

Rename original executable:

$ cd \path\to\foo\
$ mv foo foo.moved

Create wrapper as foo :

#!/bin/sh
\path\to\foo\foo.moved "$@" &
FOO_PID=$!
echo $FOO_PID >\tmp\foo.pid

make it executable :

chmod +x foo

The next time the program is run, you get the pid in \tmp\foo.pid .

0

If your OS (unspecified in o/p) doesn't support process tracing, consider replacing the child image with a wrapper, assuming the new process loads a new image.

0

Shell methods

When you run a command in a shell you can find out the PID of the last process that was run in the background using the special variable $! in a Bash shell.

For example:

$ sleep 5 &
$ echo $!
8648

Also when you background a process the PID of that process is returned via the console like this:

$ sleep 5 &
[1] 8648    

Another method would be to use pgrep -P <PPID>. For example:

# PID of bash shell
$ echo $$
8376

# run fake job
$ sleep 120 &
[1] 8891

# pgrep PPID
$ pgrep -P 8376
8891

valgrind

There is another method if you can inject the following in front of the execution of the program you're trying to get the child PIDs to:

$ valgrind --trace-children=yes <cmd>

For example:

# sample.bash
#/bin/bash

ls

$ valgrind --trace-children=yes ./sample.bash
...
==17734==      possibly lost: 0 bytes in 0 blocks
==17734==    still reachable: 33,606 bytes in 95 blocks
==17734==         suppressed: 0 bytes in 0 blocks
==17734== Rerun with --leak-check=full to see details of leaked memory
==17734== 
==17734== For counts of detected and suppressed errors, rerun with: -v
==17734== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
==17733== 
==17733== HEAP SUMMARY:
==17733==     in use at exit: 36,409 bytes in 879 blocks
...

The 17733 is the PPID and the PID 17734 is the child PID that get's invoked (ls).

  • How does that help? (Unless the parent happens to be a shell script.) – Gilles Jul 15 '13 at 21:36
  • @Gilles - those were merely to demonstrate a method. The use of pgrep -P is one approach. The $! is useful if the task is backgrounded, since the result could be captured when the command is invoked. – slm Jul 15 '13 at 21:52
  • The pgrep method only works if you manage to run pgrep during the lifetime of the process, which is very short. – Gilles Jul 15 '13 at 21:54
  • @Gilles - agreed. But it is a method. Audit trailing would be the only other method I can think of. – slm Jul 15 '13 at 22:14
  • @Gilles - psacct is another method, but doesn't offer the OP the context of searching by PPID, only by process name (lastcomm). Looking through the docs, I don't see the ability to search for a processes' child processes either. – slm Jul 15 '13 at 22:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.