在 shell 脚本中,我尝试启动一个与 shell 脚本具有相同标准输入的后台命令。
#!/bin/sh
# ...
the-program &
但是,the-program
上面的方法将无法访问与 shell 脚本相同的标准输入。根据我的外壳手册(破折号(1)):
如果 shell 不是交互式的,则异步命令的标准输入将设置为
/dev/null
。
我尝试过the-program & <&0
,但似乎没有达到预期的效果;的标准输入the-program
仍然是/dev/null
.
我考虑过通过复制 shell 脚本的标准输入来创建一个新的文件描述符,并以某种方式将该新的文件描述符传递给后台进程。但是,后台进程必须以某种方式将该新文件描述符重定向到其标准输入(替换/dev/null
)。我不知道这个想法是否可行,我也不知道如何在 POSIX sh 中实现它。
答案1
是的,这很烦人POSIXsh
规范的要求通过非交互式 shell 调用异步启动的命令(当monitor
未启用 IOW 作业控制选项时)将其标准输入重定向到 /dev/null。
如果禁用作业控制(请参阅
set
、-m
),则在执行任何显式重定向之前,异步列表的标准输入应被视为分配给与 具有相同属性的文件/dev/null
。如果启用作业控制,则不会发生这种情况。在所有情况下,标准输入的显式重定向应覆盖此活动。
通常的解决方法是:
{ cmd <&3 3<&- & } 3<&0
这听起来像你的想法。
例子:
$ sh -c 'readlink /proc/self/fd/0 & wait' < /
/dev/null
$ sh -c '{ readlink /proc/self/fd/0 <&3 3<&- & } 3<&0; wait' < /
/
另一种选择是使用即使在仿真zsh
中也忽略该要求的方法:sh
$ zsh -c 'readlink /proc/self/fd/0 & wait' < /
/
$ zsh --emulate sh -c 'readlink /proc/self/fd/0 & wait' < /
/