14

该手册指出,三通是一种“管件”工具。案例[1]让我感到困惑:

1.案例

echo "foo bar" | sudo tee -a /path/to/some/file

2.案例

:w !sudo tee %

很难从案例中理解 tee 的逻辑。三通是如何工作的?

4

8 回答 8

37

tee用于拆分命令管道,允许您将命令的输出保存到文件沿管道发送。在您给出的第一个示例中:

echo "foo bar" | sudo tee -a /path/to/some/file

"foo bar" 将回显到标准输出并附加到/path/to/some/file. 将三通想象成管道中的“T”形接头,将输出分成另外两个管道。

于 2009-04-18T23:28:37.243 回答
14

tee通常用于拆分程序的输出,使其既可以显示也可以保存在文件中。该命令可用于在数据被另一个命令或程序更改之前捕获中间输出。tee 命令读取标准输入,然后将其内容写入标准输出。它同时将结果复制到指定的文件或变量中

tee [OPTION]... [FILE]...

例如

tee [ -a ] [ -i ]... [ File ]...
  • -a将输出附加到 File 的末尾而不是覆盖它。

  • -i忽略中断。

在此处输入图像描述

使用sudo问题中的示例并附加到文件中

ls -l | sudo tee -a file.txt 
于 2016-08-26T11:49:59.480 回答
12

tee复制stdinstdout(like cat) 并另外将所有内容写入命名文件。以这种方式使用它sudo可以让人们将信息推送到特权模式,并同时监控是否有正确的东西到达那里。

另请注意,由于在 shell 中处理重定向的方式,几乎等同于

sudo echo "foo bar" > /path/to/some/file

将不起作用,因为重定向将由调用用户而不是由sudo目标用户完成。

于 2009-04-18T23:28:08.320 回答
4

案例说明

1. 使用 sudo- 和 -tee 命令提升权限

这个例子不仅仅是逻辑,而是惯例。显示了升级权限的约定:

echo "Body of file..." | sudo tee root_owned_file > /dev/null

此示例显示 tee 用于绕过 sudo 命令中的固有限制。sudo 无法将标准输出通过管道传输到文件。通过将其标准输出流转储到 /dev/null,我们还抑制了控制台中的镜像输出。

2. 用 Vim 运行 sudo-commands

由于您可以在 Vim 中使用 Sudo 命令,因此如果您忘记以 sudo 身份运行,您可以使用该命令。它在诸如 /etc/init.d/ 之类的地方很有用,您可以在其中找到只读文件。

使用 tee 命令的逻辑

它就像 Git 中的一个分支,或者更好,请参阅Rick Copeland 的 T 类比。希望修改后的示例(原始)有助于理解其用途:

curl "http://en.wikipedia.org/wiki/Pipeline_(Unix)" | tee original_site | sed 's/[^a-zA-Z ]/ /g' | tr 'A-Z ' 'a-z\n' | grep '[a-z]' | sort -u | comm -23 - /usr/share/dict/words
于 2009-08-24T07:52:24.027 回答
2

请记住,目标tee不限于常规文件,还可以是设备、FIFO 等。此外,您可以通过管道传输到另一个tee调用,等等。:-)

于 2009-04-18T23:34:05.187 回答
1

我发现该tee命令在调试包含长管道的 shell 脚本时非常有用。这是一个可怕的 shell 脚本的结尾,该脚本在 Perl 中被重写了十年,但它仍然有效。(它最后一次修改是在 1998 年,碰巧。)

# If $DEBUG is yes, record the intermediate results.
if [ "$DEBUG" = yes ]
then
    cp $tmp.1 tmp.1
    cp $tmp.2 tmp.2
    cp $tmp.3 tmp.3
    tee4="| tee tmp.4"
    tee5="| tee tmp.5"
    tee6="| tee tmp.6"
    tee7="| tee tmp.7"
fi

# The evals are there in case $DEBUG was yes.
# The hieroglyphs on the shell line pass on any control arguments
# (like -x) to the sub-shell if they are set for the parent shell.
for file in $*
do
    eval sed -f $tmp.1 $file                $tee4 |
    eval sed -f $tmp.3                      $tee5 |
    eval sh ${-+"-$-"}                      $tee6 |
    eval sed -f $tmp.2                      $tee7 |
    sed  -e '1s/^[  ]*$/--@/' -e '/^--@/d'
done

运行的三个 sed 脚本非常糟糕——我不打算展示它们。这也是eval. 正常的临时文件名($tmp.1 等)由固定名称(tmp.1 等)保存,中间结果保存在 tmp.4 .. tmp.7 中。如果我正在更新命令,它将使用 ' "$@#"' 而不是 ' $*',如图所示。而且,当我调试它时,参数列表中只有一个文件,因此对调试文件的践踏对我来说不是问题。

请注意,如果您需要这样做,您可以一次创建多个输入副本;无需将一个tee命令输入另一个命令。

如果有人需要它,我有一个tee被调用的变体,tpipe它将输出的副本发送到多个管道而不是多个文件。即使其中一条管道(或标准输出)提前终止,它也会继续运行。(有关联系信息,请参阅我的个人资料。)

于 2009-04-19T00:58:31.240 回答
0

tee只是将输出镜像到一个文件中,该文件可以指定为tee的参数。

如果您显示tee被称为超级用户(通过sudo),其唯一目的是作为超级用户而不是执行回显的用户编写文件。

于 2009-04-18T23:28:35.183 回答
0

tee命令只是创建 N+1 个文件,一个副本传递给标准输出,其他副本传递给提供给tee的参数(即文件),其中 N 是传递给tee的参数数量。

于 2014-10-31T06:40:01.073 回答