例如,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_handle
Ubuntu 上的默认设置,
$ 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 对相关问题的报告之后。