为什么这不起作用?
我看到它的方式是打开 fd 3 并将其发送到 dev nul。
然后稍后您的路线 fd 3 到 fd 2。
我想要完成的是在我的脚本中使用 fd 3 作为默认管道到 void 但如果需要可以路由到 stderr 或文件进行检查的标准信息。
MyScript.bash
exec 3>/dev/null
echo spo >&3
这对标准错误没有任何影响:
./MyScript.bash 3>&2
为什么这不起作用?
我看到它的方式是打开 fd 3 并将其发送到 dev nul。
然后稍后您的路线 fd 3 到 fd 2。
我想要完成的是在我的脚本中使用 fd 3 作为默认管道到 void 但如果需要可以路由到 stderr 或文件进行检查的标准信息。
MyScript.bash
exec 3>/dev/null
echo spo >&3
这对标准错误没有任何影响:
./MyScript.bash 3>&2
当您运行脚本时,shell 会将文件描述符 3 附加到 stderr。
但是,在您的脚本中,它用于exec
将文件描述符 3 数据发送到位存储桶,基本上覆盖了您在运行脚本时所做的事情。
解决此问题的一种方法是在启动脚本时不进行重定向。而是将可选参数与您要使用的文件一起传递:
./MyScript # with no parameter
./MyScript /tmp/xyzzy # with a parameter
然后让你的脚本完全控制:
fd3file=/dev/null
if [[ "$1" != "" ]] ; then
fd3file="$1"
fi
exec 3>${fd3file}
它不需要使用参数,您可以使用任何信息源,例如环境变量、配置文件条目等。然而,基本前提是 - 让脚本做出决定。
现在,您可以利用以下事实在多个层(shell 和脚本重定向)上执行此操作:
exec
如果发生重定向错误,将失败并返回代码 1。以下脚本显示了这一点。它尝试复制fd 3
并fd 4
检测失败。失败意味着fd 3
未打开,因此我们将其连接到/dev/null
. 成功意味着它是打开的,所以我们不要管它,因为用户已经将它连接到了某个东西:
#!/bin/bash
# Try and duplicate fd 3 (without ugly error message)
( exec 4>&3 ) 2>/dev/null
# Figure out whether fd3 was open.
if [[ $? -eq 1 ]] ; then
# It was not open so we need redirect.
echo 'redirect failed, need to exec 3>/dev/null'
exec 3>/dev/null
else
# It was, open so we leave fd3 alone (and close fd4 duplicate).
echo 'redirect worked, leave fd3 alone'
exec 4>-
fi
echo 'fd3 content' >&3
以下记录显示了它的实际应用。首先,没有基于 shell 的重定向导致脚本连接fd 3
到/dev/null
:
pax> ./qq.sh
redirect failed, need to exec 3>/dev/null
pax> cat qq
cat: qq: No such file or directory
接下来,一个基于shell 的重定向 (to qq
) 不理会fd 3
,然后您可以看到重定向到qq
已经发生:
pax> ./qq.sh 3>qq
redirect worked, leave fd3 alone
pax> cat qq
fd3 content