我想跟踪现有进程,尤其是它们的参数(如环境变量、cwd 目录、stdout 等)。我能做到。但是,我无法获得有关短期进程的信息)。例如:
如果我运行:
sleep 120 &
# get info from /proc/`pgrep sleep`
这很容易。
但是,如果我的进程立即终止或者我不知道进程的 PID(但我预计会创建一些进程)怎么办?
答案1
作为普通用户的一种方法是exec
包装器,假设程序是通过PATH
搜索运行的。也就是说,你的包装program
#!/bin/sh
env > /some/log/file
... (any other desired logging commands here) ...
exec /path/to/real/program "$@"
必须首先存在于 中PATH
,因此您可能有PATH=/some/wrapper/dir:$PATH
一个完全为要记录的program
真实名称命名的包装器,并且在包装器中您可以使用原始包装器替换包装器。如果程序通过完全限定的路径运行,那么可能需要摆弄类似的东西,或者相关应用程序可能会提供更改路径的选项?program
program
program
exec
LD_PRELOAD
因为root
使用类似sysdig
(各种 sysdig 示例)因为它可以匹配您感兴趣的临时进程名称,并且可以逐步深入到您感兴趣的内容,假设程序ls
以某个用户身份运行:
sudo sysdig "proc.name = ls and user.name = jhqdoe" | tee log
运行log
后相当冗长的文件显示一个条目,该条目可能提供您所需的几乎所有内容(环境被截断):ls
execve
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...
通过用户指南和其他文档,上述内容可以精确到仅调用execve
和显示的完整环境:
sudo sysdig -p "%proc.env" "proc.name = ls and user.name = jhqdoe and evt.type = execve" | tee xxx
调整-p
以显示您想要的内容;您还可以使用凿子从实时捕获或保存文件等中提取您想要的内容。
答案2
你必须使用forkstat(1)
或其他一些使用的程序过程连接器界面。不幸的是,您只能以 root 身份执行此操作。另外,它不可扩展或可编写脚本,因此如果您还希望它打印进程的环境、其控制 tty 等,forkstat(1)
您可能必须编写自己的程序,将 proc 连接器中的数据与 from 中的数据结合起来。procfs
这是一种非常粗略的“扩展”方法,forkstat(1)
可以打印二进制文件的实际路径和进程的当前目录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";
}
'
作为普通用户,您唯一的解决方案是运行父进程,通过以下方式启动这些短期进程(或其祖先之一):
strace -s1024 -vfe trace=execve prog args ...
该-s
选项控制将打印多少 argv 和 env 字符串strace
。通过运行程序strace
可能会对性能产生相当大的影响。可能还有其他更友好/可编写脚本的替代方案,但如果普通用户要使用它们,则strace(1)
它们都必须使用,因此不要期望它们有本质上的不同。ptrace(2)