模拟空 STDIN 到分离命令

模拟空 STDIN 到分离命令

我想最后用“command &”或“nohup command &”来分离命令,但它在分离后立即停止。

命令不太具体,如果它在输入上收到 eof,它会中断,因此 /dev/null 作为输入将导致结束和通常有效的解决方案:

$ command < /dev/null > /dev/null 2>&1 &

不工作...

unix/linux 中是否有其他设备可以替代 /dev/null 并表现得像空输入,但不发送 eof。

(顺便说一句,command是非常有用的组播工具emcast,我可以尝试自己修补它,或者为此目的找到修补版本......但似乎问题可以在外部解决)

我添加此编辑是为了使我的问题更清楚。我制作了这个 2 行的 C 程序,运行完美:程序名称是“donothing”

#include <unistd.h>
int main() {  while (1)  { sleep(10); } return 0; }

这就是我正在寻找的,一些设备/程序,什么也不做,但保持其标准输出打开。 (“command & ... disown”和“nohup command &”)都有效。

$ donothing | mycommand >/dev/null & 
$ disown %1

运行良好,所以现在的问题只是:什么 UNIX 设备/程序的行为就像我的“无所事事”。

答案1

对于您的命令来检测eof,它必须从标准输入读取。所以想必它正在等待一些输入。所以听起来你需要的不是一个空输入(/dev/null正是为此目的),而是永远不会出现的输入。

它可以用管道来模拟,没有人会在另一端写入如下内容:

sleep 999999999 | the-command

或者为了避免运行额外的sleep命令,可以使用命名管道来完成:

fifo=$(mktemp -u) &&
  mkfifo "$fifo" &&
  (rm "$fifo" && the-command <&3 3<&- &) 3<> "$fifo"

这里使用中间文件描述符来解决/dev/null当您启动命令时 shell 隐式连接 stdin 的事实&(除非您像我们这里一样添加显式 stdin 重定向<&3)。

在 Linux 上(可能仅在 Linux 上),您还可以执行以下操作:

the-command < /dev/fd/1 3>&1 > /dev/null | :

/dev/fd/1其中 fd 1 连接到一个管道,在 Linux 上,其行为类似于命名管道。也就是说,当您以读取模式打开它时,您将获得管道的读取端。

因此,上面的 fd 0 将连接到管道的读取端,该管道的另一端位于 的 fd 3 上the-command。因为the-command不会在其 fd 3 上写入任何内容,所以read对 fd 0 的任何尝试都将阻塞(或者非阻塞读取将返回还没有什么可读的,或者选择/轮询将返回没什么可读的the-command如果它除了等待永远不会到来的输入之外还做其他事情,那么可能会这样做)。

答案2

你需要使用命令disown。这将从运行这些命令的当前 shell 中释放 STDIN/STDOUT。

% disown -a

-或者-

% sleep 100 &
[1] 7987
% disown %1

请参阅bash 手册页了解更多详情。

disown [-ar] [-h] [jobspec ...] 如果没有选项,每个 jobspec 都会从活动作业表中删除。如果给出 -h 选项,则每个作业规范不会从表中删除,但会被标记,以便在 shell 收到 SIGHUP 时不会将 SIGHUP 发送到作业。如果不存在作业规范,并且未提供 -a 和 -r 选项,则使用当前作业。如果未提供 jobspec,则 -a 选项表示删除或标记所有作业;不带 jobspec 参数的 -r 选项将操作限制为正在运行的作业。除非作业规范未指定有效作业,否则返回值为 0。

答案3

我需要这样的东西来从自动化测试系统(Jenkins)运行期望脚本。当 Expect 检测到 stdin 上的 EOF 时,它会自动关闭 stdout,这会导致对 stdout 的所有写入失败并终止测试。我通过简单地将其标准输入设为 /dev/zero 来解决这个问题。

mycommand </dev/zero

相关内容