为什么使用“&”运行无效进程会关闭终端?

Nes*_*cio 6 bash

例如,a&在 bash 中运行时,终端窗口关闭,我希望在那里启动一个新进程,然后是一条错误消息(类似于,例如grep &)。

是什么导致了这种行为?是故意的吗?

编辑:根据要求,

yuvalw@UX410UQK:~$ echo $-
himBH
Run Code Online (Sandbox Code Playgroud)

我还尝试在 bash 中打开另一个 bash 以获得额外的输出。我的输入bash后跟a&一些新行:

yuvalw@UX410UQK:~$ bash
yuvalw@UX410UQK:~$ a&
[1] 15323
yuvalw@UX410UQK:~$ exit
yuvalw@UX410UQK:~$ a: command not found

yuvalw@UX410UQK:~$
Run Code Online (Sandbox Code Playgroud)

这里a&再次调用将关闭终端窗口。

编辑2:更多回声

yuvalw@UX410UQK:~$ echo "$BASH_VERSION $SHELLOPTS $BASHOPTS"
4.3.48(1)-release braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:progcomp:promptvars:sourcepath
Run Code Online (Sandbox Code Playgroud)

陷阱:

yuvalw@UX410UQK:~$ trap
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
Run Code Online (Sandbox Code Playgroud)

输入退出:

yuvalw@UX410UQK:~$ type exit
exit is a shell builtin
Run Code Online (Sandbox Code Playgroud)

PROMPT_COMMAND(空):

yuvalw@UX410UQK:~$ echo $PROMPT_COMMAND
Run Code Online (Sandbox Code Playgroud)

PS1:

yuvalw@\UX410UQK:~$ echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$
Run Code Online (Sandbox Code Playgroud)

编辑 3:打开一个新终端似乎不会发生这种情况,而且我可以运行a&得很好,但是经过cd一段时间后,问题又回来了。在这两种情况下,command_not_found_handle 看起来都一样。

yuvalw@yuvalw-UX410UQK:~$ type command_not_found_handle

command_not_found_handle is a function
command_not_found_handle () 
{ 
    if [ -x /usr/lib/command-not-found ]; then
        /usr/lib/command-not-found -- "$1";
        return $?;
    else
        if [ -x /usr/share/command-not-found/command-not-found ]; then
            /usr/share/command-not-found/command-not-found -- "$1";
            return $?;
        else
            printf "%s: command not found\n" "$1" 1>&2;
            return 127;
        fi;
    fi
}
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 14

那是 中的一个错误bash,已在 4.4中修复。

如果您command_not_found_handle()定义了钩子(在未找到命令时调用),bash即使未找到的命令是在后台启动的,也将其置于前台。

然后,根据时间,如果 shell 在将 tty 设备command_not_found_handle置于前台后从 tty 设备读取命令行,read()那么EIO当后台进程从终端设备读取并忽略 SIGTTIN 信号时,会返回错误。

bash会将其视为用户输入的文件结尾,就像您按下了Ctrl+D

可以通过执行以下操作来重现该问题:

$ command_not_found_handle() { sleep 20; }
$ a &
$ x
Run Code Online (Sandbox Code Playgroud)

即使第一次read()成功是因为它在被置于前台之前启动command_not_found_handle,按下后的第二次和后续读取x将失败并导致外壳退出。

使用command_not_found_handleUbuntu 上的默认设置,

$ a & true &
Run Code Online (Sandbox Code Playgroud)

还导致 shell 退出,因为 SIGCHLD 在true返回第一个中断时read()会导致第二个中断,而处理程序仍在前台运行。

然而,在一般情况下,该错误似乎不太可能触发,因为 shell 在写入提示之前也将自己置于前台,因此command_not_found_handle必须tcsetpgrp()在正确的时刻将自己置于前台(执行)(在主 shell 进程将自己置于前景并在它开始从 tty 设备读取之前)。

这是在 2015 年 4 月修复的,此提交(CWRU.log 中的 4/23 条目)是在 Valentin Bajrami 对相关问题的报告之后