Bash 重定向可执行文件';s stdout/stderr,但不是来自shell的调用时间错误

Bash 重定向可执行文件';s stdout/stderr,但不是来自shell的调用时间错误,bash,scripting,io-redirection,Bash,Scripting,Io Redirection,我有一个简单的bash脚本,它在后台启动一个可执行文件,并将stdout+stderr重定向到一个日志文件: #!/usr/bin/bash myexec >& logfile & 它起作用了。然而,myexec的输出并不是唯一被重定向的东西:当试图调用myexec时,bash发出的任何消息也将进入logfile。也就是说,如果bash没有找到myexec,我就看不到myexec:没有这样的文件或目录错误,因为它直接指向logfile,而不是终端。这种行为令我恼火,因为我

我有一个简单的bash脚本,它在后台启动一个可执行文件,并将stdout+stderr重定向到一个日志文件:

#!/usr/bin/bash
myexec >& logfile &
它起作用了。然而,
myexec
的输出并不是唯一被重定向的东西:当试图调用
myexec
时,
bash
发出的任何消息也将进入
logfile
。也就是说,如果
bash
没有找到
myexec
,我就看不到
myexec:没有这样的文件或目录
错误,因为它直接指向
logfile
,而不是终端。这种行为令我恼火,因为我最终不知道脚本是否成功启动了
myexec


我突然想到,脚本可以在尝试调用它之前测试
myexec
的存在性,但我想知道是否有一种方法可以使重定向本身只执行
myexec
的输出,而不执行shell的输出,被重定向。

不可能按照OP描述的方式分离输出。正如Charles Duffy在他的评论中解释的那样,打开(或未能打开)可执行文件
myexec
的系统调用发生在Bash分叉一个新进程之后,此时所有I/O重定向都已设置。但是,有一种变通方法足以满足OP中所述的目的,即“了解脚本是否成功启动myexec”:


不,实际上没有,不过也许您可以尝试一下这个近乎重复的答案:execve()系统调用不会返回
这样的文件或目录,它发生在
fork()和所有文件描述符重定向之后。我看不到一个明显的方法来实现一个没有这种行为的shell,至少在不创建对一个操作系统的硬依赖的情况下,这个操作系统具有
O_CLOEXEC
来维护一个单独的机制,将错误传递回FIFO,FIFO在成功执行时自动关闭。谢谢你们@查尔斯·达菲,你的解释清楚了它为什么会这样@tripleee,从你的链接中,我看到有一些并不太丑陋的黑客。我已经确定了表单
myexec>logfile2>&1&&echo“ok”>&2 | | echo“nope.”>&2
。这里唯一的问题是,它将任何来自
myexec
的非零退出状态视为无法分叉。不过,正如您所说的,在UNIX按原样设计的情况下,这种限制几乎是不可避免的——这也是为什么systemd具有
Type=forking
(因此,在进程分叉之前的故障被视为进程未成功启动,而分叉进程最终以非零状态退出被视为成功启动,然后是随后的故障)和
Type=notify
(进程负责通过套接字写入其当前状态的更新)。
myexec > logfile 2>&1 && echo "ok" >&2 || echo "nope." >&2