Pan*_*dey -7 bash io-redirection shell-script
我有一个从其中一个网站获得的脚本。当我运行它时,它给出了“Hello”作为输出,但我无法理解脚本的工作原理。
谁能解释一下脚本实际上在做什么?
#!/bin/bash
echo hello
if test -t 1; then
# Stdout is a terminal.
exec >log
else
# Stdout is not a terminal.
npipe=/tmp/$$.tmp
trap "rm -f $npipe" EXIT
mknod $npipe p
tee <$npipe log &
exec 1>&-
exec 1>$npipe
fi
echo goodbye
Run Code Online (Sandbox Code Playgroud)
该脚本可能是一个示例,您需要更改echo goodbye以执行更多操作。
让我们假设脚本被调用demo。当您运行它时,正如您所见,它首先输出“hello”。然后查看输出是否到达终端,目的是决定您是否正在运行
demo
Run Code Online (Sandbox Code Playgroud)
或者
demo | some other program
Run Code Online (Sandbox Code Playgroud)
如果是前者,那么它只是将文件其余部分的输出发送到名为log. 如果后者然后 if 创建named pipe并启动一个tee进程将写入命名管道的所有内容复制到demo脚本的输出(因此some other prog将获取它)和名为log. 然后它安排将文件其余部分的输出发送到这个命名管道。它还安排在demo完成时删除命名管道。
exec 1>&-不需要线。
所有这一切的最终结果是“再见”这个词被写入文件“日志”。如果你跑了,demo | cat你会在屏幕上看到“你好”和“再见”。
正如@derobert 在评论中指出的那样,命名管道具有可预测的名称。根据此项的设置,umask可能允许某人demo通过阅读它(因此tee看不到它)或添加额外的内容进行tee复制来破坏输出。这是对可用于针对已知或可预测名称的许多标准攻击的补充。可以预先设置软链接或硬链接,以导致打开或截断其他文件。在我的 linux 系统上,如果文件已经存在,mknod 将失败,但由于脚本忽略了此错误,因此exec 1>$npipe将执行该错误。