我有一个从某个网站获得的脚本。当我运行它时,它给出了“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
答案1
该脚本可能是一个示例,您需要更改以echo goodbye
执行更多操作。
让我们假设该脚本被称为demo
.当您运行它时,正如您所看到的,它首先输出“hello”。然后它会查看输出是否发送到终端,以决定您是否正在运行
demo
或者
demo | some other program
如果是前者,那么它只是将文件其余部分的输出发送到名为log
.如果后者则创建一个named pipe
并启动一个tee
进程,将写入命名管道的所有内容复制到脚本的输出demo
(因此some other prog
将得到它)和名为log
.然后它安排将文件其余部分的输出发送到该命名管道。它还安排在demo
完成时删除命名管道。
exec 1>&-
不需要该线。
所有这一切的最终结果是将“再见”一词写入文件“log”中。如果你跑步,demo | cat
你会在屏幕上看到“你好”和“再见”。
正如 @derobert 在评论中指出的那样,命名管道有一个可预测的名称。根据此设置,可能会允许某人通过读取它(因此看不到它)或添加额外的内容进行复制来umask
破坏输出。这是对可用于针对已知或可预测名称的许多标准攻击的补充。可以提前设置软链接或硬链接以导致其他文件被打开或截断。在我的 Linux 系统上,如果文件已存在,mknod 将失败,但由于脚本忽略此错误,因此将执行该文件。demo
tee
tee
exec 1>$npipe