我想最后用“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