“tee”的目的是什么?

R M*_*oog 96 shell tee

tee我见过的所有用法都是这样的:

 do_something | tee -a logfile
Run Code Online (Sandbox Code Playgroud)

或者:

do_something_else | tee logfile
Run Code Online (Sandbox Code Playgroud)

tee为那些不知道你可以用 shell 管道重定向做同样的事情的人发明的吗?如:

do_something >> logfile
Run Code Online (Sandbox Code Playgroud)

或者:

do_something_else > logfile
Run Code Online (Sandbox Code Playgroud)

它实际上是一样的,而且打字所需的键盘敲击次数更少。我没有看到哪些隐藏功能tee

Eug*_*eck 246

您没有看到的是do_something | tee -a logfile将输出放入logfile 放入标准输出,而do_something >> logfile将其放入日志文件。

的目的tee是产生一个输入、多个输出的场景——就像在“T”交叉中一样。

编辑

关于如何tee更无缝地使用sudo. 这是无关紧要的:catdd或者buffer如果您不需要多个输出,则可以更好地提供具有更好性能的这种可能性。使用tee它所设计,而不是什么“也可以做”

  • 多输出是关键。`tee` 甚至可以接受多个参数并一次写入多个文件。 (37认同)
  • 我会称它为三通*管件*,而不是十字路口(如在道路交叉路口?)东西从一个方向进来,两个方向出去。 (20认同)
  • 我将如何以直接的方式使用 `cat` 而不是 `tee`,例如 `echo /var/work/core.%p | 须藤三通/proc/sys/kernel/core_pattern`?`echo /var/work/core.%p | sudo cat > /proc/sys/kernel/core_pattern` 不起作用,因为重定向是由非 sudo shell 处理的。至于`dd`,`echo /var/work/core.%p | sudo dd of=/proc/sys/kernel/core_pattern` 可以工作,但 `dd` 通常是一个强大的工具,能够造成巨大的破坏,尤其是在 `sudo` 下。至于`buffer`,默认情况下它没有安装在我必须使用的任何基于 RedHat 或 Ubuntu 的发行版中(或 MacOS)... (8认同)
  • @EugenRieck 我确实理解您关于 in:out 之间的 1:n 关系是主要功能的观点。但是,在这种情况下,内置的 `cat` 和 `/bin/cat` 都不适合我。`cat` 来自哪里并不重要 - `>` 仍将由顶级(非 sudo)shell 处理。在这种情况下,`tee` 比 `cat` 的优势在于它允许将输出文件作为命令行参数(而不是重定向)传递。`dd` 当然是一个可行的选择,尽管我仍然喜欢使用 `tee` (4认同)
  • @EugenRieck 什么 shell 内置了 `cat` 和 `tee`?什么版本的 `sudo` 可以运行 shell 内置函数? (4认同)
  • @EugenRieck 使用 `sudo cat > ...` _not_ 工作,除非您的 shell(解析命令行的东西)具有写入文件的权限,否则它_无法_工作。`> ...` 由 shell 解析,它_不_作为参数提供给应用程序。它与内置无关。 (4认同)

ber*_*ieb 121

Tee 不是没用

也许你知道吗?如果没有,请继续阅读!或者,如果您知道它是如何工作的,但不确定它为什么存在,请跳到最后以了解它如何与 Unix 哲学相适应。

什么目的tee

最简单的是,它获取标准输入上的数据并将其写入标准输出和一个(或多个)文件。在将一个输入分成两个输出(和两个方向)的方式上,它被比作管道三通

例子

让我们以你的第一个例子为例:

do_something | tee -a logfile
Run Code Online (Sandbox Code Playgroud)

这将获取输出do_something并将其附加到日志文件,同时还将其显示给用户。事实上,维基百科页面上tee的第二个例子是:

要查看命令的输出并将其附加到现有文件:

  lint program.c | tee -a program.lint
Run Code Online (Sandbox Code Playgroud)

这会在计算机上显示 lint program.c 命令的标准输出,同时将其副本附加到 program.lint 文件的末尾。如果 program.lint 文件不存在,则会创建它。

下一个示例还有另一个用途:权限升级

允许升级权限:

cat ~/.ssh/id_rsa.pub | ssh admin@server "sudo tee -a /root/.ssh/authorized_keys2 > /dev/null"
Run Code Online (Sandbox Code Playgroud)

此示例显示 tee 用于绕过sudo命令中的固有限制。sudo无法将标准输出通过管道传输到文件。通过将其标准输出流转储到 中/dev/null,我们还抑制了控制台中的镜像输出。上面的命令通过将用户的公钥安装到服务器的密钥授权列表,让当前用户通过 ssh 访问服务器。

或者,也许您想获取一个命令的输出,将其写在某处并将其用作另一个命令的输入?

您还可以使用 tee 命令将命令的输出存储到文件中,并将相同的输出作为输入重定向到另一个命令。

以下命令将备份 crontab 条目,并将 crontab 条目作为输入传递给将执行替换的 sed 命令。替换后,将作为新的cron作业添加。

$ crontab -l | tee crontab-backup.txt | sed 's/old/new/' | crontab –
Run Code Online (Sandbox Code Playgroud)

(归功于Tee 命令用法示例

Tee 与 Unix 哲学一起工作:

编写只做一件事并把它做好的程序。编写程序以协同工作。编写程序来处理文本流,因为这是一个通用接口。

(归功于Unix 哲学的基础知识

tee 适合所有这些:

  • 它只做一件事:创建一个额外的输入副本
  • 它可以与其他程序一起使用,因为它是让其他程序协同工作的粘合剂(如果您愿意,也可以使用“T”形管道),如上例所示
  • 它通过操纵在标准输入上给出的文本流来做到这一点

  • @Joe:`sudo tee -a` 可能是最近的一项创新(我第一次在 Ubuntu 指南/wiki 中看到它,特别是在 `/proc/sys` 中设置内容,因为切换到 Ubuntu 是在我切换到 `sudo` 时基于系统(默认情况下如何配置 Ubuntu)而不是使用带有 root 密码的 `su`)。我认为`tee`早于`sudo`,所以这不是`tee`存在的原因。你不需要`tee`,交互输入比`sudo sh -c 'cat > output'` 更短。 (3认同)
  • 这不是您正在解决的 sudo 限制,而是 shell 对 > 解释的限制。当您使用 sudo 运行命令时,其标准输出会被发送回您的 shell 程序,并且使用 > 进行进一步重定向时,将使用 shell 的权限运行。如果您想使用提升的权限进行写入,则需要将管道的提升部分作为写入的内容。有很多方法可以做到这一点,具体取决于您要达到的效果。如果你真的想使用 > 'sudo bash -c "command > outfile" ' 之类的东西就可以了。 (2认同)

Att*_*tie 70

它实际上是一样的,而且打字所需的键盘敲击次数更少。

完全不一样...

以下似乎有些等价,但它们不是:

$ echo "hi" > test.txt
Run Code Online (Sandbox Code Playgroud)
$ echo "hi" | tee test.txt
hi
Run Code Online (Sandbox Code Playgroud)

关键的区别在于前者只将数据写入了命名文件,而后者写入hi了终端(stdout命名文件,如下所示:

重定向 vs tee


tee允许您将数据写入文件在向前的管道中使用它,允许您做有用的事情 - 例如在管道的中途保留数据:

grep '^look ' interesting_file.txt \
  | tee interesting_lines.txt \
  | sort
Run Code Online (Sandbox Code Playgroud)

或者,您可以写入具有提升权限的文件,而无需为整个管道提供提升权限(此处echo,shell 以用户身份运行,同时tee以 身份写入文件root):

echo 0 \
  | sudo tee /proc/sys/net/ipv4/ip_forward
Run Code Online (Sandbox Code Playgroud)

使用tee,您可以写入多个文件( stdout):

echo "hi" \
  | tee a.txt b.txt
Run Code Online (Sandbox Code Playgroud)

还可以使用execwithtee将脚本的所有输出记录到文件中,同时仍然允许观察者 ( stdout) 查看数据:

exec > >( tee output.log )
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记 bash 脚本中的 `exec > >(tee "$LOGFILE") 2>&1`,它允许脚本将 stdout 和 stderr 输出到 stdout 和 `$LOGFILE` 指向的文件。 (2认同)

voi*_*ces 28

这是 T 恤:
在此处输入图片说明

T形管件。它有一个入口和两个独立的出口。
换句话说,它将一根管子一分为二;就像一个岔路口。

同样,tee管道 ( |) 允许您将标准输入重定向到两个单独的输出。


示例
比如说,您键入ls /
您将获得类似于以下内容的输出:

Applications    Network     Users       bin        dev      net      private    tmp         var
Library         System      Volumes     cores      etc      home     opt        sbin        usr
Run Code Online (Sandbox Code Playgroud)

将输出重定向到文本文件 ,ls / > ls.txt并且 shell 中不显示任何输出,仅在生成的文本文件中显示。

想要查看输出,并同时将其传递给文本文件吗?
将 a 添加tee到您的管道 ( |) 中,即:ls / | tee ls.txt


比较两者:

ls /          >          ls.txt
ls /        | tee        ls.txt
Run Code Online (Sandbox Code Playgroud)

  • +1 图片,据我们所知,价值一千字 (4认同)

LPC*_*hip 18

不。您碰巧提到了少数几个确实可以使用>>>运算符重定向到文件的示例之一。

但是 Tee 可以做的远不止这些。因为你通过管道连接到它,然后你可以通过管道连接到其他东西。

维基百科页面上列出了一个很好的例子:

find "4DOS" wikipedia.txt | tee 4DOS.txt | sort > 4DOSsorted.txt
Run Code Online (Sandbox Code Playgroud)

基本上,您可以通过管道连接到 Tee,因此您可以通过管道从 Tee 连接到其他东西。如果你只想写一个日志文件,是的,那么你真的不需要 Tee。


UTF*_*F-8 18

tee远非无用。我一直在使用它,很高兴它存在。如果您有要拆分的管道,这是一个非常有用的工具。一个非常简单的例子是,您有一些$d要压缩的目录,并且还想对其进行哈希处理,因为您很偏执(就像我一样)并且不相信存储介质能够可靠地保存数据。您可以先将其写入磁盘,然后对其进行散列,但如果存档在散列之前已损坏,则会失败。此外,您必须阅读它,如果您经常处理数百 GB 大小的文件,您就会知道,如果不是必须的,您真的不想再次阅读它们。

所以我所做的就是这样:

tar -c "$d" | tee >(sha256sum) >(cat > "$d"".tar") > /dev/null
Run Code Online (Sandbox Code Playgroud)

它创建 tar 球并将其通过管道传输到 tee,然后通过管道将其传输到两个子壳,其中一个是散列的,另一个是写入磁盘。

如果您想对一个大文件执行多个操作,这也很棒:

< file.tar.gz tee >(sha256sum) >(tar -xz) /other/storage/location/file.tar.gz > /dev/null
Run Code Online (Sandbox Code Playgroud)

读取文件一次,对其进行哈希处理(这样您就可以检查它是否仍然是它应该的样子),提取它,然后将它复制到不同的位置。没必要为此读三遍。

  • 如果您担心重定向的词法顺序,您也可以编写 `&lt; file.tar.gz tee &gt;(sha256sum) ...`。这并没有改变这样一个事实,即不需要一个完全独立的过程来将单个文件提供给 `tee`。 (6认同)
  • 挑剔:`tee` 不会创建子外壳;调用shell运行`sha5sum`和`cat`并将它们的输出连接到传递给`tee`的文件描述符。此外,“cat”的无用使用;你可以使用输入重定向让 `tee` 直接从 `file.tar.gz` 读取。 (3认同)

stu*_*dog 12

在@bertieb 的回答中吹毛求疵说这个例子显示了 tee 被用来绕过 sudo 命令中的固有限制。sudo 无法将标准输出通过管道传输到文件。

没有固有的限制,只是对命令处理方式的误解。

例子:

sudo echo 0 > /proc/sys/net/ipv4/ip_forward

当前外壳解析命令行。它找到输出重定向并执行它。然后它执行命令,它是sudo并提供剩余的命令行作为执行命令的参数。如果当前 shell 没有 root 权限,则输出重定向将失败。

echo 0 | sudo tee /proc/sys/net/ipv4/ip_forward

这是有效的,因为输出重定向被推迟到tee命令,此时它确实具有 root 权限,因为它是通过sudo.

sudo bash -c "echo 0 > /proc/sys/net/ipv4/ip_forward"

这是有效的,因为执行重定向的 shell 具有 root 权限。

  • 此外,您可能需要 `sudo` 命令,但不需要输出文件,重定向工作正常:`sudo foo-needs-privilege &gt; /tmp/this-output-file-doesnt` (2认同)

小智 10

正如其他人所提到的,管道输出到tee命令会将输出写入文件和标准输出。

tee当我想从需要很长时间运行的命令中捕获输出时,我经常使用,同时还想在命令使其可用时直观地检查输出。这样,在检查输出之前,我不必等待命令完成运行。

似乎还没有提到的(除非我错过了)是该tee命令还可以一次写入多个文件。例如:

ls *.png | tee a.txt b.txt
Run Code Online (Sandbox Code Playgroud)

*.png当前目录中的所有文件一次写出到两个不同的文件(a.txtb.txt)。

事实上,你可以tee像这样一次向几个不同的文件输入文本:

$ tee --append a.txt b.txt c.txt d.txt
These lines are appended to four different files,
and are also written to stdout.
CTRL-D
Run Code Online (Sandbox Code Playgroud)


小智 9

tee 最常见的用途是在将文本发送到文件(或多个文件)的同时在终端上查看文本。您问题的措辞假设您只将文本写入日志文件。我有脚本编写文件名或目录名列表来触发文件(由其他脚本异步处理),我使用 tee 将相同的内容发送到标准输出。所有标准输出都指向日志。所以我在我想要的地方有我的文本,我有一个日志条目记录我这样做,所有这些都来自一个'echo'语句

tee 也是 Unix 中制作多个相同文件的最佳方法。我偶尔会用它来制作多个空文件,就像这样......

:|tee file01 file02 file03
Run Code Online (Sandbox Code Playgroud)

  • 为什么不“触摸”?(更明显的发生了什么) (5认同)