获取从我当前运行的进程中分叉的进程列表?

div*_*shm 6 process ps process-management

我正在为 bash 脚本编写一个包装应用程序,并希望该应用程序跟踪从用户脚本启动的工具/进程。我想知道确定由父进程产生的子进程列表的最佳方法是什么。

我试过

  1. 定期调用ps命令并构建进程树(如 ps -ejH),但这会错过运行速度非常快的进程。
  2. 使用像forkstat这样的工具使用 proc 连接器接口,但只能以提升的权限运行。虽然这提供了正确的数据,但以 sudo 身份运行在我的情况下不起作用?

任何建议如何实现?

mur*_*uru 9

如果您使用的是 Linux,则可以用于strace跟踪进程使用的系统调用。例如:

~ strace -e fork,vfork,clone,execve -fb execve -o log ./foo.sh
foo bar
~ cat log
4817  execve("./foo.sh", ["./foo.sh"], [/* 42 vars */]) = 0
4817  clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f1bb563b9d0) = 4818
4818  execve("/bin/true", ["/bin/true"], [/* 42 vars */] <detached ...>
4817  --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=4818, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
4817  clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f1bb563b9d0) = 4819
4817  clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f1bb563b9d0) = 4820
4820  execve("/bin/echo", ["/bin/echo", "foo", "bar"], [/* 42 vars */] <detached ...>
4817  --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=4820, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
4817  +++ exited with 0 +++
4819  execve("/bin/sleep", ["sleep", "1"], [/* 42 vars */] <detached ...>
Run Code Online (Sandbox Code Playgroud)

您可以看到脚本使用clone(2)系统调用分叉了三个进程(PID 4818、4819、4820),并且execve(2)这些分叉进程中的系统调用显示了执行的命令。

  • -e fork,vfork,clone,execve 将 strace 输出限制为这些系统调用
  • -f 跟随子进程
  • -b execveexecve到达时与进程分离,因此我们看不到对子进程的进一步跟踪。


小智 7

pstree -p `pgrep NetworkManager`\nNetworkManager(1638)\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80dhclient(3594)\n                     \xe2\x94\x9c\xe2\x94\x80{NetworkManager}(1645)\n                     \xe2\x94\x9c\xe2\x94\x80{NetworkManager}(1647)\n                     \xe2\x94\x94\xe2\x94\x80{NetworkManager}(7363)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想这就是你正在寻找的。

\n\n

使用直接 pid 或 pgrep 和进程名称。

\n\n

-p 用于打印子进程的 pid。

\n