1

为什么这不起作用?

我看到它的方式是打开 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
4

1 回答 1

1

当您运行脚本时,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 3fd 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
于 2013-03-10T09:03:14.777 回答