subshel​​l奇怪行为的后台进程

subshel​​l奇怪行为的后台进程

我想知道为什么一些类似的 bash 命令会有这样的行为。

我有一个 bash 脚本foo

#!/usr/bin/env bash

while true
do
    echo "reading"
    read data
    echo $data
    echo "stderr msg" >&2
    sleep 1
done

这是一个无限循环,一次从 stdin 读取一行并输出同一行。我还有一个 bash 脚本bar

#!/usr/bin/env bash

./foo &

以下命令bash在 Ubuntu 18.04 的终端(v.4.4.19)中运行(假设脚本位于工作目录中):

  1. ./foo &

    • 当它尝试从标准输入读取时停止,根据这个答案

    • 正如预期的那样,当控制终端被杀死时被杀死。

  2. (./foo &)

    • 似乎会自动连续地从标准输入输入新的输入。当尝试从标准输入读取时,它不应该停止吗?无论它得到什么,在回显时都不会显示,因此我猜测它是 EOF 字符。

    • 即使控制终端被终止后仍继续运行。查看 的输出ps,控制终端从 pts/ 变为X到 ?。在不使用disownor的情况下这是如何发生的nohup? (但是,在杀死最初的控制终端后,每次写入时都会产生“写入错误:输入/输出错误”,我想这是因为它的标准输出与现在关闭的终端相关联。对吗?)

  3. bash -c "./foo &"

    看起来行为与 2) 完全相同。

  4. ./bar

    看起来与 2) 和 3) 完全相同。

  5. 添加bash -c "~/foo"(no &) 作为启动应用程序

    其行为与 2)、3) 和 4) 类似,但不同之处在于:

    • 它的控制终端是桌面ttyX
    • 你不能(你能吗?)杀死它的控制终端。

    这些差异对我来说并不奇怪,只是它不断地注入新的输入。

我的猜测是 2) - 5) 都使用了某种子 shell,其 stdin 被重定向到类似的东西/dev/null,尽管我非常不确定并寻求更准确的答案。

答案1

&在 shell 中运行的命令没有启用的作业控制(例如在脚本或(...)子 shell 中)将其标准输入从/dev/null和重定向SIGINTSIGQUIT设置为SIG_IGN。来自 susv4标准:

如果禁用作业控制(请参阅set-m),则在执行任何显式重定向之前,异步列表的标准输入应被视为分配给与 具有相同属性的文件/dev/null。如果启用作业控制,则不会发生这种情况。在所有情况下,标准输入的显式重定向应覆盖此活动。

也可以看看

您的脚本“连续输入”数据并不正确./foo——它在尝试读取时收到 EOF——/dev/null您应该检查read.

答案2

您的子 shell 是非交互式的;只有交互式 shell 会被自动杀死。

相关内容