我有一些运行程序的脚本(不是我编写的),有些脚本在一些输入上出现了段错误。我批量执行这些操作,运行时间长达一周,我想知道哪些输入触发了问题。目前,我收到 Bash 的通知,说我的某个脚本出现了段错误。但问题不在于脚本,而在于第三方程序及其输入。如果我有输入的名称,我就可以解决这个问题。
我的 Bash 脚本中调用的当前形式是(例如程序“autofix”)
for indata in base*.fix; do
autofix $indata >${indata/.fix/.stdout} &
done
如您所见,它们是在后台启动的,在我的主力服务器上,一次启动的可能多达 100 个左右,所以我无法判断哪一个失败了,而且我没有足够的耐心一次尝试所有 100 个,因为每个可能都要花一个小时。捕获 stderr 不会捕获任何内容,所以我正在寻找其他想法。
答案1
我找到了一个内联解决方案,只需尝试一下我在 Bash 中已经知道的东西(或者至少习惯遇到的东西)。为了测试和说明,我使用了一个我编写的只会导致 SEGFAULT 的小型 C 程序:
// Cause a seg fault
#include <stdlib.h>
#include <stdio.h>
int main() {
char *zero = 0;
*zero = 0;
printf("Hey, how did I get away with this?");
exit(EXIT_SUCCESS);
}
然后经过一些尝试(见下面的评论)我最终在 Bash 中得到了这个简单的模式(它可能只有一行,但我提供了一种更易读的形式):
if ./segfault
then
echo strange success
else
echo this died with return code $?
fi
这不会因为 SEGFAULT 而死掉,而只是注意到了这一点。因此输出是“此进程死掉”,而不是“奇怪的成功”或整个进程故障。
如果需要,这种方法可以显示区分 SEGFAULT 和其他形式的进程故障的错误代码。
最后,在决定我需要更多信息之后,我想出了这种形式的解决方案(简化了一些细节):
// expecting input files with names beginning with "input".
// the names become prefixes for the output file names.
for input in input*; do
dodgy-code ${input} >${input}-stdout 2>${input}-stderr ||
echo Error in ${input} with code $? >>error-list
done
// clean up empty report files
for report in *stderr ; do
if [ -f $report && ! -s $report ] then
rm $report
fi
done
// now there are stdout files for all inputs, stderr files for
// the ones that returned an error code and an "error-list" file
// listing the inputs that caused problems and the error code returned.