4

I want to trace existing process and especially their parameters (like environment variables, cwd directory, stdout and so on). I can do it. However, I cannot get that information about short-lived processes). For example:

If I run:

sleep 120 & 
# get info from /proc/`pgrep sleep` 

and it is easy.

But, what if my process is immediately terminated or I don't know PID of process (but I expect that some process will be created).

4

One approach as an ordinary user is an exec wrapper, assuming the programs are run via a PATH search. That is, your wrapper for program

#!/bin/sh
env > /some/log/file
... (any other desired logging commands here) ...
exec /path/to/real/program "$@"

must exist first in PATH, so you might have PATH=/some/wrapper/dir:$PATH and then a wrapper program named exactly for the real program to be logged, and in the wrapper program you replace your wrapper with the original program using exec. If the program is being run by fully qualified paths then it may be necessary to fiddle around with something like LD_PRELOAD or perhaps the application in question may give an option to change the path?

As root tracing would be quite simple with something like sysdig (various sysdig examples) as that can match the ephemeral process names you are interested in, and can incrementally drill down to what you are interested in, say the program ls run as some user:

sudo sysdig "proc.name = ls and user.name = jhqdoe" | tee log

The rather verbose log file after an ls is run shows an execve entry that may give almost everything you need (the environment is truncated):

9734 16:12:49.683389228 1 ls (20542) < execve res=0 exe=ls args=--color=auto. tid=20542(ls) pid=20542(ls) ptid=20052(bash) cwd= fdlimit=1024 pgft_maj=0 pgft_min=61 vm_size=404 vm_rss=4 vm_swap=0 comm=ls cgroups=cpuset=/.cpu_cgroup=/.cpuacct=/.mem_cgroup=/.devices=/user.slice.freezer=/.ne... env=XDG_SESSION_ID...

Via the user guide and other documentation, the above can be made precise to only the execve call and the full environment shown via:

sudo sysdig -p "%proc.env" "proc.name = ls and user.name = jhqdoe and evt.type = execve" | tee xxx

Adjust -p to show what you want; you could also use a chisel to extract what you want from a live capture or a save file, etc.

  • I second sysdig +1 – Rui F Ribeiro Feb 9 at 15:52
  • sysdig is great but how to get information about stdout, stderr and stdin? – Gilgamesz Feb 9 at 20:02
  • what sort of information about those descriptors? dipping into them can be problematical given how they can be shared between processes – thrig Feb 10 at 15:39
3

You'll have to use forkstat(1) or some other program using the proc connector interface. Unfortunately, you can only do that as root. Also, forkstat(1) isn't extensible or scriptable, so you'll probably have to write your own program combining the data from the proc connector with that from procfs if you also want it to print the environment of a process, its controlling tty, etc.

Here is a very crude way to "extend" forkstat(1) to also print the actual path to the binary and the current directory of a process upon execve:

stdbuf -o0 forkstat -e fork,exec | perl -anle '
  print;
  if($F[1] eq "exec"){
     print "\texe = ", readlink "/proc/$F[2]/exe";
     print "\tcwd = ", readlink "/proc/$F[2]/cwd";
  }
' 

As an ordinary user, your only solution is run the parent process starting those short-lived processes (or one of its ancestors) via

strace -s1024 -vfe trace=execve prog args ...

The -s option controls how much of the argv and env strings strace will print. Running programs via strace may have quite an impact on performance. There may be other more friendly / scriptable alternatives to strace(1), but they all have to use ptrace(2) if they are to be used by an ordinary user, so don't expect them to be essentially different.

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.