題 'tee'的目的是什麼?


所有的用法 tee 我見過的是這樣的:

 do_something | tee -a logfile

要么:

do_something_else | tee logfile

tee 發明的那些不知道你可以用殼管重定向做同樣的事情?如:

do_something >> logfile

要么:

do_something_else > logfile

它實際上是相同的,鍵入的鍵盤命中率較低。我沒有看到什麼隱藏的功能 tee


86
2017-09-10 11:14


起源


這個手冊頁的第一行是如何回答的 “......並寫入標準輸出和文件”?答案很有意思,但廣泛討論管道是如何有用的只是強化了Q的外觀 太寬泛, 也許應該已經關閉。 - Xen2050
@ Xen2050一個問題不能歸咎於過於寬泛的答案。這個問題非常具體,就像現在一樣 評分最高的答案。 - Jon Bentley
@JonBentley的問題聽起來不像 “具有足夠細節的特定問題,以確定適當的答案” (如關閉對話框所示)。它聽起來像這樣: “如果你的問題可以通過整本書來回答,或者有許多有效的答案(但無法確定哪些 - 如果有的話 - 是正確的話),那麼它對於我們的格式來說可能過於寬泛。” (資料來源: 幫助中心) - Xen2050
@ Xen2050我們是否在閱讀相同的問題?這對我來說似乎非常具體 - 三通與管道有什麼區別?用兩句話充分回答了問題。遠非整本書。一些答案的事實 選擇切線與問題的範圍無關。 - Jon Bentley
@JonBentley:我們在讀相同的問題嗎? RMoog有點像 暗示 一個相當集中的問題 - 有什麼區別 tee  和 I / O重定向?事實上,它說“殼 管 重定向


答案:


你沒看到的是那個 do_something | tee -a logfile 將輸出放入 logfile   到了stdout,而 do_something >> logfile 說得好 只要 進入日誌文件。

的目的 tee 是產生一個輸入,多輸出的場景 - 就像在'T'交叉點。

編輯

有關於如何評論 tee 使更多的無限使用 sudo。這不是重點: catdd 或者更好 buffer 如果您不需要多個輸出,則可以提供更好的性能。使用 tee 它的設計,而不是它“也可以做”


240
2017-09-10 11:22



多輸出是關鍵。 tee 甚至可以採用多個參數並一次寫入多個文件。 - Kamil Maciorowski
我稱之為發球檯 管道配件,而不是一個十字路口(如在道路交叉口?)東西以一種方式出現並且雙向都出現。 - user20574
我該怎麼用 cat 以一種簡單的方式而不是 tee 在例如 echo /var/work/core.%p | sudo tee /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)中...... - Digital Trauma
@EugenRieck我確實得到了關於in:out作為主要功能之間的1:n關係的觀點。但是,既不是內置的 cat 也不 /bin/cat 在這種情況下為我工作。無論在哪裡都沒關係 cat 來自 - > 仍將由頂級(非sudo)shell處理。的優點 tee 過度 cat 在這種情況下,它允許輸出文件作為命令行參數(而不是重定向)傳遞。 dd 肯定是一個可行的選擇,雖然我仍然贊成 tee 為了這 - Digital Trauma
@EugenRieck有什麼shell cat 和 tee 作為內置者?什麼版本的 sudo 可以運行shell內置? - wjandrea


Tee 並非沒用

也許你知道嗎?如果沒有,請繼續閱讀!或者如果你知道它是如何工作的,但不確定 為什麼 它存在,跳到最後看看它是如何適應Unix哲學的。

什麼  的目的 tee

最簡單的是,它採用標準輸入數據並將其寫入標準輸出和一個(或多個)文件。它被比作一個 水暖三通件 在它將一個輸入分成兩個輸出(和兩個方向)的方式。

例子

我們來看你的第一個例子:

do_something | tee -a logfile

這需要輸出 do_something 並將其附加到logfile,同時還將其顯示給用戶。事實上, 維基百科頁面上 tee 將此作為第二個例子:

要查看命令的輸出並將其附加到現有文件:

  lint program.c | tee -a program.lint

這將在計算機上顯示lint program.c命令的標準輸出,同時將其副本附加到program.lint文件的末尾。如果program.lint文件不存在,則創建它。

下一個例子有另一個用途: 權限升級

允許升級權限:

cat ~/.ssh/id_rsa.pub | ssh admin@server "sudo tee -a /root/.ssh/authorized_keys2 > /dev/null"

這個例子顯示了tee用於繞過其中的固有限制 sudo 命令。 sudo 無法將標準輸出傳遞給文件。通過將其標準輸出流轉儲到 /dev/null,我們還抑制控制台中的鏡像輸出。上面的命令通過將用戶的公鑰安裝到服務器的密鑰授權列表,通過ssh為當前用戶root訪問服務器。

或者您可能想要獲取一個命令的輸出,在某處寫入並將其用作另一個命令的輸入?

您還可以使用tee命令將命令的輸出存儲到文件,並將相同的輸出重定向為另一個命令的輸入。

以下命令將備份crontab條目,並將crontab條目作為輸入傳遞給sed命令,該命令將執行替換。替換後,它將被添加為新的cron作業。

$ crontab -l | tee crontab-backup.txt | sed 's/old/new/' | crontab –

(歸功於 Tee命令用法示例

Tee 適用於Unix哲學:

編寫完成一件事並做得好的程序。編寫程序以協同工作。編寫程序來處理文本流,因為這是一個通用接口。

(歸功於 Unix哲學的基礎知識

tee 適合所有這些:

  • 它做了一件事:創建一個額外的輸入副本
  • 它適用於其他程序,因為它是粘合劑(或者如果你願意的話,是'T'管道件),它可以讓其他程序一起工作,就像上面的例子一樣
  • 它通過操縱標準輸入上給出的文本流來實現

118
2017-09-10 11:23



@Joe: sudo tee -a 可能是一個更新的創新(我首先在Ubuntu指南/維基中看到它,特別是在設置內容 /proc/sys,因為當我切換到一個時,切換到Ubuntu sudo 基於系統(默認情況下如何配置Ubuntu)而不是使用 su 用root密碼)。我認為 tee 早 sudo,所以這不是理由 tee 現有。你不需要 tee 為此,交互式輸入比簡短 sudo sh -c 'cat > output'。 - Peter Cordes
有了像bash這樣的現代貝殼,你可以 tee 餵兩條管道,比如 foo | tee >(pipe2) | pipe1。或者另一個有趣的是 ffmpeg ... |& tee /dev/tty | sed 's/.*\r// > encode.log 在tty上以交互方式查看狀態行更新,同時刪除以回車而非實際記錄的換行符結束的“行”。 (即過濾掉狀態行更新)。一般來說,你可以堅持下去 tee /dev/tty 管道中的任何位置作為調試打印。 - Peter Cordes
它不是你正在解決的sudo的限制,而是對shell的解釋的限制。當您使用sudo運行命令時,它的stdout會被發送回您的shell程序,並且使用shell的權限進行進一步的重定向。如果您想使用提升的權限進行編寫,則需要將管道的提升部分作為寫入內容。有很多方法可以做到這一點,具體取決於你想要的效果。如果你真的想使用> sudo bash -c這樣的命令> outfile“'將完成這項工作。 - Perkins
確實,@ Perkins。 shell解析 > 並在sudo之前設置重定向 exec是的,所以它是 無疑 不是sudo的限制,它不處理它從未見過的事情。 :)當我解釋它時,我通常會嘗試將其稱為“sudo工作流​​程”或類似術語,而不是描述sudo本身。 - dannysauer
sudo tee -a 是恕我直言,濫用發球檯。使用 sudo cat, sudo dd 或(在許多情況下表現最佳) sudo buffer 如果你不需要多個輸出。 - Eugen Rieck


它實際上是相同的,鍵入的鍵盤命中率較低。

它完全不一樣......

以下似乎有點等同,但它們不是:

$ echo "hi" > test.txt
$ echo "hi" | tee test.txt
hi

關鍵的區別在於前者只將數據寫入命名文件,而後者已編寫 hi 到終端(stdout 命名文件,如下所示:

redirect vs tee


tee 允許您將數據寫入文件  在前向管道中使用它,允許您執行有用的操作 - 例如將數據保存在管道的中途:

grep '^look ' interesting_file.txt \
  | tee interesting_lines.txt \
  | sort

或者,您可以使用提升的權限寫入文件,而無需為整個管道提供提升的權限(此處為 echo 以用戶身份運行,而 tee 寫入文件為 root):

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

tee,你可以寫到很多文件(  stdout):

echo "hi" \
  | tee a.txt b.txt

它也可以使用 exec 同 tee 將所有腳本的輸出記錄到文件中,同時仍然允許觀察者(stdout)看數據:

exec > >( tee output.log )

68
2017-09-10 11:29



不要忘記 exec > >(tee "$LOGFILE") 2>&1 在一個bash腳本中,它允許腳本輸出stdout和stderr,stdout和指向的文件 $LOGFILE。 - rexkogitans
@rexkogitans 2>&1是不是那個cmd批處理語法? - dmb
@dmb:它是“將stderr(= 2)發送到與stdout(= 1)相同的位置的shell語法” - psmears
@rexkogitans這真的是一個公平的問題,我真的不知道你已經十年沒有使用過“Windoze”了。我用 2>&1 刪除輸出和錯誤到Windows中的txt文件。 - dmb
@dmb我很抱歉聽起來很粗魯。這都是關於psmears的評論。顯然,Windows在這裡採用了Unix風格。 - rexkogitans


這是一個發球檯:
enter image description here

T形管件。它有一個入口和兩個獨立的出口。
換句話說,它將一個管道分成兩個;就像在路上的叉子。

同樣的, tee 是一個管道(|),允許您將標準輸入重定向到兩個單獨的輸出。



比如說,你輸入 ls /
你會得到一個看起來像這樣的輸出:

Applications    Network     Users       bin        dev      net      private    tmp         var
Library         System      Volumes     cores      etc      home     opt        sbin        usr

將輸出重定向到文本文件, ls / > ls.txt,並且shell中不顯示任何輸出,僅在結果文本文件中顯示。

想要查看輸出,並同時將其傳遞給文本文件?
添加一個 tee 到你的煙斗(|)即: ls / | tee ls.txt


比較兩者:

ls /          >          ls.txt
ls /        | tee        ls.txt

25
2017-09-11 16:26



我們知道的圖片+1代價值千言萬語 - Sergiy Kolodyazhnyy
如果你選擇了一個花園軟管T片,那麼你應該與Doug McIlroy最初的比喻一致。 - JdeBP
@JdeBP對不起,我不知道是誰。他是該實用程序的原作者還是其他什麼?數據流和物理電流通常與液壓系統進行比較,但您可能知道這一點。無論如何,我只是選擇了這種風格來保持它的簡單。我實際上是為了讓它熟悉,但花園品種往往有更多的Y形和/或視覺上複雜的附件,用於附加配件等。雖然它基本上是相同的。 - tjt263
M. Douglas McIlroy,作者 這個著名的備忘錄 誰 曾在貝爾實驗室工作過 和 說服Ken Thompson將管道輸入Unix。 - JdeBP


不。您碰巧提到了幾個可以確實使用重定向到文件的示例之一 > 和 >> 運營商。

但是Tee可以做得更多。因為你管道它,你可以管道到其他東西。

一個很好的例子列在 維基百科頁面

find "4DOS" wikipedia.txt | tee 4DOS.txt | sort > 4DOSsorted.txt

基本上,你可以管道到Tee,所以你可以從Tee管道到其他東西。如果您只想寫一個日誌文件,是的,那麼您真的不需要Tee。


17
2017-09-10 11:21





tee 遠非沒用。我一直都在使用它,很高興它存在。如果您想要拆分管道,這是一個非常有用的工具。一個非常簡單的例子是你有一些目錄 $d你想要tar並且你也想哈希它,因為你是偏執狂(就像我)並且不相信存儲介質可靠地保存數據。您 可以 首先將它寫入磁盤然後對其進行哈希處理,但如果存檔在哈希處理之前被損壞則會失敗。此外,你必須閱讀它,如果你處理大小幾百GB的文件,你會知道你真的不想再讀它們,如果它不是必須的話。

所以我所做的只是這樣:

tar -c "$d" | tee >(sha256sum) >(cat > "$d"".tar") > /dev/null

它創建了tar球並將其管道連接到三通,然後將其管道連接到兩個子殼,其中一個子殼被散列,另一個子殼被寫入磁盤。

如果你想對一個大文件執行幾個操作,這也很棒:

< file.tar.gz tee >(sha256sum) >(tar -xz) /other/storage/location/file.tar.gz > /dev/null

讀取文件一次,對其進行哈希處理(這樣您就可以檢查它是否仍然如此),提取它並將其複製到其他位置。無需為此閱讀三次。


16
2017-09-10 15:31



雞蛋裡挑骨頭: tee 沒有創造子殼;調用shell運行 sha5sum 和 cat 並將其輸出連接到傳遞給的文件描述符 tee。還有,無用的使用 cat;你可以使用輸入重定向 tee 直接閱讀 file.tar.gz。 - chepner
@chepner你對第一次感嘆是對的,但你對第二次感嘆完全錯了。我喜歡按順序編寫我的管道,所以表示右邊的輸入對於可讀性來說是可怕的,這樣做顯然客觀上不如我的方法,完全不是我的主觀偏好。 cat 是愛。 cat 就是生活。 - UTF-8
你也可以寫 < file.tar.gz tee >(sha256sum) ... 如果你擔心重定向的詞法排序。這並沒有改變這樣一個事實,即只需要將單個文件提供給一個完全獨立的進程 tee。 - chepner
@chepner很酷,謝謝!今天學到了一些東西。 :) - UTF-8
的代價 開始  cat 相對較低。額外100 GiB的寫入+讀取系統調用的成本肯定會浪費額外的CPU時間和內存帶寬,以用於您提出的大型文件示例。請記住,內存帶寬是所有內核的共享資源,更不用說複製帶來的L3緩存的額外污染。在啟用了Specter + Meltdown緩解的x86上,系統調用比以前更昂貴。在該副本的過程中,您正在耗盡可測量的額外CPU時間。也 >(cat > foo)不容易理解 foo,IMO。 - Peter Cordes


Nitpick對@ 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權限。


11
2017-09-10 14:33



此外,您可能需要 sudo 對於該命令,但不是對於正在輸出的文件,重定向工作正常: sudo foo-needs-privilege > /tmp/this-output-file-doesnt - Dennis Williamson