我有一个大型可执行文件的外壳包装器。它做了这样的事情:
run/the/real/executable "$@" &
PID=$!
# perform
# a few
# minor things
wait $PID
# perform some
# post-processing
它在之后所做的事情之一wait
是检查核心转储并处理进程崩溃,但是,到那时该进程已经死亡并且某些信息不再可用。
shell 脚本可以在将致命信号 (SIGSEGV
或SIGBUS
) 传递给子进程本身之前拦截它吗?
例如,然后我就能够执行lsof -p $PID
以获取包装进程在终止之前打开的文件列表......
更新:我尝试使用strace
捕获接收信号的进程。不幸的是,似乎有一场竞赛——当strace
报告孩子的信号时,孩子正在出去,并且不知道是否lsof
会获得其文件列表......
这是测试脚本,它会生成/bin/sleep
并尝试获取它已打开以进行写入的文件。有时会/tmp/sleep-output.txt
按应有的方式报告,有时列表为空......
ulimit -c 0
/bin/sleep 15 > /tmp/sleep-output.txt &
NPID=$!
echo "Me: $$, sleep: $NPID"
(sleep 3; kill -BUS $NPID) &
ps -ww $NPID
while read line
do
set -x
outputfiles=$(lsof -F an -b -w -p $NPID | sed -n '/^aw$/ {n; s,.,,; p}')
ps -ww $NPID
lsof -F an -b -w -p $NPID
break
done < <(strace -qq -p $NPID -e trace=signal 2>&1)
echo $outputfiles
wait $NPID
上述测试需要使用ksh
or bash
(为了使< <(...)
构造起作用)。
答案1
据我所知,没有 shell 方法可以完成您正在尝试的操作,必须通过自定义程序来完成。
使用ptrace()
监视进程,类似于调试器的方式。当进程收到信号时,它将被停止,并且监视程序将收到通知(其调用wait()
将返回,并且WIFSTOPPED(status)
将为true)。
然后它可以运行lsof -p <pid>
以列出进程的打开文件,然后调用ptrace(PTRACE_CONT, pid, NULL, 0)
以重新启动进程。