我看到了以下shell脚本。我想我已经了解它正在做什么,但我仍然不明白使用这么多重定向和文件描述符的目的是什么?例如,exec 3>&1
,do something 2>&1 1>&3
和exec 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>&-
答案 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引用相同的文件 - 原始stdout
。 1>&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
。你没有看到这种事情正常完成,因为要求有点不寻常。