这些重定向和文件描述符的目的是什么?

时间:2014-06-04 20:30:44

标签: bash shell

我看到了以下shell脚本。我想我已经了解它正在做什么,但我仍然不明白使用这么多重定向和文件描述符的目的是什么?例如,exec 3>&1do something 2>&1 1>&3exec 3>&-

#-Open file descriptor (fd)
exec 3>&1

#-Create a form and then store data to $VALUES variable
VALUES=$(dialog \
    --keep-tite \
    --ok-label "Submit" \
    --backtitle "Linux User Managment" \
    --title "Useradd" \
    --form "Create a new user" \
    15 50 0 \
    "Username:" 1 1 "$user"     1 10 10 0 \
    "Shell:"    2 1 "$shell"    2 10 15 0 \
    "Group:"    3 1 "$groups"   3 10 8 0 \
    "HOME:"     4 1 "$home"     4 10 40 0 \
2>&1 1>&3)

# close fd
exec 3>&-

# display values just entered
echo "$VALUES"
你可以告诉我为什么他们有必要吗?是因为正在使用dialog实用程序吗?我问,因为我从未见过人们在简单的命令中这样做,如ls等。

exec 3>&1
ls 2>&1 1>&3
exec 3>&-

2 个答案:

答案 0 :(得分:4)

通常dialog通过stdout向用户显示其对话框,它是文件描述符1,从stdin读取用户的击键,即文件描述符0,并输出值由用户填写stderr,即文件描述符2.

引入额外文件描述符的原因是通过$(command…)替换读取值(与反引号相同)。命令替换将内部命令(在本例中为dialog…)发送到其stdout,并将其填入外部命令(在本例中为VALUES=…)。

2>&1重定向会使dialog将字段值发送到stdout,并将其捕获到VALUES。因此,dialog需要不同的文件描述符来向用户显示对话框。 exec 3>&1复制原始stdout文件描述符。也就是说,在该命令之后,文件描述符3和文件描述符1引用相同的文件 - 原始stdout1>&3重定向使dialog显示其原始stdout的对话框。

换句话说,引入文件描述符3的原因是暂时“保存”stdout

答案 1 :(得分:2)

细分很简单:

exec 3>&1

写入文件描述符3的任何内容都将与文件描述符1,标准输出相同。

VALUES=$(command ...arguments... 2>&1 1>&3)

这里,写入文件描述符2的任何内容,标准错误,将与文件描述符1,标准输出相同。但是,然后更改标准输出的定义,以便写入标准输出的任何内容都与文件描述符3位于同一位置。这是在命令替换$(...)操作中,因此标准输出通常在文件中捕获。这意味着变量VALUES可以保存command写入标准错误的任何内容,而原始标准输出可以获得命令写入标准输出的任何内容。

最后:

exec 3>&-

关闭文件描述符3;尝试写入它将从此处失败。

您对命令的模拟应该是:

exec 3>&1
variable=$(ls 2>&1 1>&3)
exec 3>&-

这将捕获ls$variable的任何错误,同时允许您查看标准输出上写的ls。你没有看到这种事情正常完成,因为要求有点不寻常。