我有这个脚本:
#!/bin/bash
# -> dump.$pid
ulimit -c unlimited
# trap ERR
set -o errexit
# also trap error in the middle of a pipe (1)
# otherwise it will only trap the error on (2)
set -o pipefail
trap 'echo "ERR $?"' ERR
echo "a"
echo "1" | ./crash | cat
echo "b"
echo "2" | ./crash
echo "c"
其按预期工作:
$ ./script.sh >& script.log
$ echo "$?"
139
$ cat script.log
a
Segmentation fault (core dumped)
ERR 139
(没有pipefail
它会打印“a b”,没有errexit
它会打印“ab c”)
但是,由于这是较大管道的一部分并在批处理系统上运行,因此可能会发生许多崩溃并且文件argv
中的信息dump.?????
不够。
那么:如何打印导致脚本错误的进程的 PID(以及预期的核心转储文件名),以便可以将其与其余所有进程一起记录?
崩溃的程序可能是较大管道的一部分(特别是它们可能并不总是位于管道的末尾,因此使用pipefail
),并且我想避免必须用包装器代码包围每个调用,或者无法程序之间直接传送数据。
答案1
事实证明,启用作业控制可以解决问题——但前提是没有SIGSEGV
陷阱,设置可以防止详细输出。
set -o errexit
set -o pipefail
set -o monitor
trap 'echo "ERR $?"' ERR
echo "hi" | ./docrash | cat
echo "not reached"
运行它可以准确地给出我正在寻找的输出,甚至更多。它打印每个子进程的 PID 并显示错误:
$ ./err.sh >& err.log
$ cat err.log
./err.sh: line 21: 25110 Done echo "hi"
25111 Segmentation fault (core dumped) | ./docrash
25112 | cat
ERR 139
$ gdb docrash core.25111
...
如果您想查看管道故障但不中止脚本,则可以组合设置:
set -o pipefail
set -o monitor
echo "hi" | ./docrash | cat
echo "pipe returned $?"
打印跟踪并继续:
$ ./err.sh
./err.sh: line 21: 25110 Done echo "hi"
25111 Segmentation fault (core dumped) | ./docrash
25112 | cat
pipe returned 139