显示或重定向shell的作业控制消息

时间:2017-07-10 23:44:24

标签: linux shell signals zsh

TL; DR

所有作业控制/崩溃消息在函数中发生时都会被隐藏。我在下面详细介绍,但是@Barmar指出可以通过在函数内部运行崩溃二进制来重现此问题,例如:

crun() { 
  /tmp/faulty $1 $2 $3
}

我在我的.zshrc中定义了一个函数来编译和放大使用以下函数运行源代码:

crun() {
    local file=$1
    shift
    local exepath="$(mktemp)"

    if [[ $file =~ "\.c$" ]]; then
        gcc -g -Wall $file -o $exepath || return $?
    else
        echo "no filetype detected"
        return 126
    fi

    $exepath "$@"
}

可以这种方式调用:

% crun source.cc arg_1 arg_2

这适用于普通程序,但是存在shell的作业控制消息(例如从段错误生成的消息)不会出现的问题。

举个例子:

% echo 'int main=0;' >> /tmp/faulty.c # a crashing c program
% crun faulty.c
% # no output generated

而等效的交互式命令会产生这个:

% g++ faulty.c -o /tmp/faulty && /tmp/faulty
[1] 2894 segmentation fault (core dumped) #  zsh's job control output for SIGSEGV

有没有办法为崩溃的可执行文件显示这些消息,其路径是动态计算的?理想情况下,无需编写自己的陷阱/信号处理程序+ exec,使用sh -c "$exepath $@"或完全编写全新的system(3)包装器

1 个答案:

答案 0 :(得分:1)

如果您将作为后台作业启动,则可以zsh从作业中打印分段错误消息,然后立即将其置于前台。

"$exepath" "$@" &
fg

这将导致zsh打印出$exepath开始作业信号的消息。

缺点是你会得到比你讨价还价更多的东西:

% crun faulty.c
faulty.c:1:5: warning: ‘main’ is usually a function [-Wmain]
 int main=0;
     ^~~~
[2] 2080
[2]  - running    "$exepath" "$@"
zsh: segmentation fault (core dumped)  "$exepath" "$@"

但如图所示,您将获得终端中打印的段错误消息。

由于消息是由交互式shell打印的,而不是失败的过程,因此如果您尝试重定向stdoutstderr,则不会重定向作业消息。

因此,一方面,如果您尝试从正在运行的流程中获取有用的输出并将其重定向到其他位置,您就不必担心工作消息会妨碍您。但是,这也意味着如果您尝试通过重定向stderr来重定向,则无法获取段错误消息。

以下是此效果的演示,为了清晰起见,在命令之间添加了换行符:

% crun good.c > test
[2] 2071
[2]  - running    "$exepath" "$@"

% cat test
Hello, world!

% crun faulty.c 2>test
[2] 2092
[2]  - running    "$exepath" "$@"
zsh: segmentation fault (core dumped)  "$exepath" "$@"

% cat test
faulty.c:1:5: warning: ‘main’ is usually a function [-Wmain]
 int main=0;
     ^~~~

有关详细信息,请参阅zsh's documentation on jobs and signals。您还可以查看the C file where the magic happens