Apa tujuan dari 'tee'?


90

Semua penggunaan yang teepernah saya lihat adalah seperti:

 do_something | tee -a logfile

Atau:

do_something_else | tee logfile

Apakah teediciptakan untuk mereka yang tidak tahu Anda dapat melakukan hal yang sama dengan pengalihan pipa shell? Seperti:

do_something >> logfile

Atau:

do_something_else > logfile

Ini praktis sama dan membutuhkan lebih sedikit hit keyboard untuk mengetik. Fitur tersembunyi apa yang tidak saya lihat tee?


62
Bagaimana ini tidak dijawab oleh baris pertama halaman manual "... dan menulis ke output dan file standar" ? Jawabannya menarik, tetapi secara luas berbicara tentang bagaimana pipa bermanfaat hanya memperkuat bagaimana Q ini tampak terlalu luas, dan mungkin seharusnya sudah ditutup.
Xen2050

3
@ Xen2050 Pertanyaan tidak dapat disalahkan untuk jawaban yang terlalu luas. Pertanyaannya sangat spesifik, seperti jawaban berperingkat tertinggi saat ini .
Jon Bentley

1
@JonBentley pertanyaannya tidak terdengar seperti "masalah khusus dengan detail yang cukup untuk mengidentifikasi jawaban yang memadai" (ketika dialog tutup berbunyi). Kedengarannya seperti ini: "jika pertanyaan Anda dapat dijawab oleh seluruh buku, atau memiliki banyak jawaban yang valid (tetapi tidak ada cara untuk menentukan mana - jika ada - yang benar), maka itu mungkin terlalu luas untuk format kami." (Sumber: Pusat Bantuan )
Xen2050

4
@ Xen2050 Apakah kita membaca pertanyaan yang sama? Tampaknya sangat spesifik bagi saya - apa perbedaan antara tee dan pipa? Itu telah dijawab secara memadai menggunakan dua kalimat. Jauh dari keseluruhan buku. Fakta bahwa beberapa jawaban memilih untuk menyinggung tidak ada hubungannya dengan ruang lingkup pertanyaan.
Jon Bentley

@ JonBentley: Apakah kita membaca pertanyaan yang sama? Jenis R Moog menyiratkan pertanyaan yang cukup fokus - apa perbedaan antara tee dan pengalihan I / O ?   Fakta bahwa ia mengatakan " pengalihan pipa shell seperti dan " bukanlah hal yang menguntungkannya, dan merupakan argumen untuk menutup sebagai tidak jelas. Tapi itu sebenarnya mengajukan beberapa pertanyaan: "Apa tujuan dari ?", " Diciptakan untuk mereka yang tidak tahu Anda bisa melakukan hal yang sama dengan pengalihan pipa shell?" Dan "Fitur tersembunyi apa yang tidak saya lihat ?". Setidaknya dua dari pertanyaan itu terlalu luas. >>>teeteetee
G-Man

Jawaban:


242

Apa yang tidak Anda lihat adalah yang do_something | tee -a logfilemenempatkan output ke logfile dan ke stdout, sementara do_something >> logfilemenempatkannya hanya ke dalam file log.

Tujuannya teeadalah untuk menghasilkan satu input, skenario banyak keluaran - sama seperti dalam persilangan 'T'.

SUNTING

Ada komentar tentang bagaimana teememungkinkan penggunaan yang lebih tidak terlihat sudo. Ini adalah intinya: cat, ddatau mungkin lebih baik buffermemberikan kemungkinan ini dengan kinerja yang lebih baik, jika Anda tidak perlu beberapa output. Gunakan teeuntuk apa yang dirancang, bukan untuk apa yang "juga bisa dilakukan"


37
Output ganda adalah kuncinya. teebahkan dapat mengambil beberapa argumen dan menulis ke banyak file sekaligus.
Kamil Maciorowski

20
Saya akan menyebutnya fitting pipa tee , bukan persimpangan (seperti di persimpangan jalan?) Barang-barang datang dalam satu arah dan keluar dua arah.
user253751

7
Bagaimana saya akan menggunakan catdengan cara yang langsung daripada teedi misalnya echo /var/work/core.%p | sudo tee /proc/sys/kernel/core_pattern? echo /var/work/core.%p | sudo cat > /proc/sys/kernel/core_patterntidak berfungsi, karena pengalihan diproses oleh shell non-sudo. Adapun dd, echo /var/work/core.%p | sudo dd of=/proc/sys/kernel/core_patternbekerja, tetapi ddsering merupakan alat yang dikuasai mampu melakukan kerusakan besar, terutama di bawah sudo. Adapun buffer, itu tidak diinstal secara default di salah satu distro RedHat- atau Ubuntu saya harus menyerahkan (atau MacOS) ...
Digital Trauma

3
@EugenRieck Saya mengerti maksud Anda tentang hubungan 1: n antara in: out sebagai fungsi utama. Namun, tidak ada builtin catatau /bin/catbekerja untuk saya dalam situasi ini. Tidak masalah dari mana catasalnya - >masih akan ditangani oleh shell tingkat atas (non-sudo). Keuntungan dari teelebih catdalam situasi ini adalah memungkinkan file output untuk dilewatkan sebagai param baris perintah (dan bukan redirect). ddtentu saja merupakan opsi yang layak, meskipun saya masih mendukung teeini
Digital Trauma

3
@EugenRieck Apa yang dimiliki shell catdan teesebagai builtin? Dan versi apa yang sudobisa menjalankan shell builtins?
wjandrea

118

Tee tidak sia-sia

Mungkin Anda tahu itu? Jika tidak, baca terus! Atau jika Anda tahu cara kerjanya, tetapi tidak yakin mengapa itu ada, lewati sampai akhir untuk melihat bagaimana itu cocok dengan filosofi Unix.

Apa adalah tujuan tee?

Paling sederhana, dibutuhkan data pada input standar dan menuliskannya ke output standar dan satu (atau lebih) file. Itu telah disamakan dengan sepotong tee pipa dengan cara membagi satu input menjadi dua output (dan dua arah).

Contohnya

Mari kita ambil contoh pertama Anda:

do_something | tee -a logfile

Ini mengambil output dari do_somethingdan menambahkannya ke file log, sementara juga menampilkannya kepada pengguna. Faktanya, halaman Wikipediatee memiliki ini sebagai contoh kedua:

Untuk melihat dan menambahkan output dari perintah ke file yang ada:

  lint program.c | tee -a program.lint

Ini menampilkan output standar dari perintah lint program.c di komputer dan pada saat yang sama menambahkan salinannya ke akhir file program.lint. Jika file program.lint tidak ada, itu dibuat.

Contoh berikutnya memiliki kegunaan lain: peningkatan izin :

Untuk memungkinkan peningkatan izin:

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

Contoh ini menunjukkan tee digunakan untuk mem-bypass batasan bawaan pada sudoperintah. sudotidak dapat mem-pipe output standar ke file. Dengan membuang stream out standarnya ke /dev/null, kami juga menekan output mirror di konsol. Perintah di atas memberikan akses root pengguna saat ini ke server lebih dari ssh, dengan menginstal kunci publik pengguna ke daftar otorisasi kunci server.

Atau mungkin Anda ingin mengambil output dari satu perintah, menulis di suatu tempat dan juga menggunakannya sebagai input ke perintah lain?

Anda juga dapat menggunakan perintah tee untuk menyimpan output dari perintah ke file dan mengarahkan output yang sama sebagai input ke perintah lain.

Perintah berikut akan mengambil cadangan entri crontab, dan meneruskan entri crontab sebagai input ke perintah sed yang akan melakukan substitusi. Setelah substitusi, itu akan ditambahkan sebagai pekerjaan cron baru.

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

(kredit untuk contoh penggunaan perintah Tee )

Tee bekerja dengan filosofi Unix:

Tulis program yang melakukan satu hal dan lakukan dengan baik. Menulis program untuk bekerja bersama. Menulis program untuk menangani aliran teks, karena itu adalah antarmuka universal.

(Kredit untuk Dasar-dasar Filsafat Unix )

tee cocok untuk semua ini:

  • ia melakukan satu hal: membuat salinan input tambahan
  • ini bekerja dengan program lain karena lem (atau sepotong pipa 'T' jika Anda suka) yang memungkinkan program lain bekerja sama seperti pada contoh di atas
  • ia melakukan ini dengan memanipulasi aliran teks yang diberikan pada input standar

3
@ Jo: sudo tee -amungkin adalah inovasi yang lebih baru (saya pertama kali melihatnya di Ubuntu panduan / wiki terutama untuk pengaturan hal-hal di /proc/sys, karena beralih ke Ubuntu adalah ketika saya beralih ke sudosistem berbasis (bagaimana Ubuntu dikonfigurasi secara default) daripada menggunakan sudengan kata sandi root). Saya pikir teemendahului sudo, sehingga tidak alasan untuk teeada. Anda tidak perlu teeuntuk itu, itu hanya lebih pendek untuk mengetik secara interaktif daripada sudo sh -c 'cat > output'.
Peter Cordes

1
Dengan kerang modern seperti bash, Anda dapat teememberi makan dua pipa, seperti foo | tee >(pipe2) | pipe1. Atau kesenangan lainnya adalah ffmpeg ... |& tee /dev/tty | sed 's/.*\r// > encode.logmelihat pembaruan baris status secara interaktif di tty, sambil menghapus "garis" yang berakhir dengan carriage-return alih-alih baris baru untuk logging aktual. (Yaitu menyaring pembaruan baris status). Secara umum, Anda dapat menempel tee /dev/ttydi mana saja dalam pipa sebagai debug-cetak.
Peter Cordes

2
Ini bukan batasan sudo yang sedang Anda kerjakan dan lebih merupakan batasan interpretasi shell tentang>. Ketika Anda menjalankan perintah dengan sudo stdout-nya akan dikirim kembali ke program shell Anda dan pengalihan lebih lanjut dengan> dijalankan dengan izin shell. Jika Anda ingin menulis dengan izin yang ditinggikan Anda harus memiliki bagian yang ditinggikan dari pipa menjadi apa yang ditulis. Ada banyak cara untuk melakukan ini tergantung pada efek apa yang Anda inginkan. Jika Anda benar-benar ingin menggunakan> sesuatu seperti 'sudo bash -c "command> outfile"' akan melakukan pekerjaan itu.
Perkins

Tepat sekali, @Perkins. Shell mem-parsing >dan mengatur redirection bahkan sebelum sudo mengerti exec, jadi pasti bukan batasan sudo yang tidak menangani hal-hal yang tidak pernah dilihatnya. :) Saya biasanya mencoba menyebut ini sebagai "alur kerja sudo" atau istilah serupa ketika saya menjelaskannya, daripada menggambarkan sudo itu sendiri.
dannysauer

sudo tee -aadalah IMHO penyalahgunaan tee. Gunakan sudo cat, sudo ddatau (dengan kinerja terbaik dalam banyak kasus) sudo bufferjika Anda tidak membutuhkan banyak output.
Eugen Rieck

70

Secara praktis sama dan membutuhkan lebih sedikit hit keyboard untuk mengetik.

Sama sekali tidak sama ...

Berikut ini tampaknya agak setara, tetapi tidak:

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

Perbedaan kritis adalah bahwa yang pertama telah menulis data hanya ke file yang bernama, sedangkan yang terakhir telah menulis hike terminal ( stdout) dan file bernama, seperti yang ditunjukkan di bawah ini:

redirect vs tee


teememungkinkan Anda untuk menulis data ke file dan menggunakannya dalam pipa selanjutnya, memungkinkan Anda untuk melakukan hal-hal yang berguna - seperti menyimpan data dari jalur pipa:

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

Atau, Anda dapat menulis ke file dengan privilege yang ditinggikan, tanpa memberikan seluruh pipeline privilege yang ditinggikan (di sini echodijalankan sebagai pengguna, sambil teemenulis ke file sebagai root):

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

Dengan tee, Anda dapat menulis ke banyak file ( dan stdout ):

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

Juga dimungkinkan untuk digunakan execdengan teemerekam semua output skrip ke file, sementara masih memungkinkan pengamat ( stdout) untuk melihat data:

exec > >( tee output.log )

2
Jangan lupa exec > >(tee "$LOGFILE") 2>&1dalam skrip bash yang memungkinkan skrip menampilkan stdout dan stderr untuk keduanya, stdout dan file yang ditunjuk oleh $LOGFILE.
rexkogitans

@rexkogitans 2> & 1 bukan sintaks cmd batch itu?
dmb

@dmb: Ini sintaksis shell untuk "kirim stderr (= 2) ke tempat yang sama dengan stdout (= 1)"
psmears

@rexkogitans Benar-benar pertanyaan yang adil, saya tidak bisa benar-benar tahu bahwa Anda belum menggunakan "Windoze" selama satu dekade. Saya gunakan 2>&1untuk melepaskan output dan berbuat salah untuk file txt di windows.
dmb

1
@ dmb Saya minta maaf karena terdengar kasar. Ini semua tentang komentar psmears. Jelas, Windows mengadopsi gaya Unix di sini.
rexkogitans

27

Ini adalah tee:
masukkan deskripsi gambar di sini

Fitting pipa berbentuk T. Ini memiliki saluran masuk, dan dua outlet terpisah.
Dengan kata lain, itu membagi satu pipa menjadi dua; seperti garpu di jalan.

Demikian pula, teeadalah pipa ( |) yang memungkinkan Anda untuk mengarahkan input standar Anda ke dua output terpisah.


Contoh
Katakanlah misalnya, Anda mengetik ls /.
Anda akan mendapatkan output yang terlihat seperti:

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

Redirect output ke file teks ls / > ls.txt,, dan tidak ada output ditampilkan di shell, hanya di file teks yang dihasilkan.

Ingin melihat hasilnya, DAN meneruskannya ke file teks pada saat yang sama?
Tambahkan teeke pipa Anda ( |) yaitu:ls / | tee ls.txt


Bandingkan keduanya:

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

4
+1 untuk gambar yang seperti yang kita ketahui bernilai ribuan kata
Sergiy Kolodyazhnyy

Jika Anda memilih sepotong pipa selang taman, Anda akan sejalan dengan metafora asli Doug McIlroy.
JdeBP

@ JdeBP Maaf, saya tidak tahu siapa itu. Apakah dia penulis asli utilitas atau semacamnya? Aliran data & arus listrik fisik sering dibandingkan dengan sistem hidrolik, tetapi Anda mungkin tahu itu. Bagaimanapun, saya hanya memilih gaya ini untuk membuatnya tetap super sederhana. Saya sebenarnya akan melakukan itu untuk membuatnya tetap akrab, tetapi varietas taman cenderung memiliki lebih banyak bentuk Y dan / atau lampiran yang rumit secara visual untuk memasang aksesori, dll. Pada dasarnya itu sama saja.
Suara


18

Tidak. Anda menyebutkan salah satu dari beberapa contoh di mana Anda memang dapat mengarahkan ulang ke file menggunakan >dan >>operator.

Tapi Tee bisa berbuat lebih banyak. Karena Anda menyalurkan ke sana, Anda kemudian dapat menyalurkan ke yang lain.

Contoh yang bagus tercantum di halaman wikipedia :

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

Pada dasarnya, Anda dapat menyalurkan ke Tee, sehingga Anda dapat menyalurkan dari Tee ke yang lain. Jika semua yang ingin Anda lakukan adalah menulis file log, ya, maka Anda tidak benar-benar membutuhkan Tee.


17

teejauh dari tidak berguna. Saya menggunakannya sepanjang waktu dan senang itu ada. Ini adalah alat yang sangat berguna jika Anda memiliki pipa yang ingin Anda pisahkan. Contoh yang sangat sederhana adalah bahwa Anda memiliki beberapa direktori $dyang ingin Anda tar dan Anda juga ingin menggunakannya karena Anda paranoid (seperti saya) dan tidak percaya media penyimpanan untuk menyimpan data dengan andal. Anda dapat menulisnya ke disk terlebih dahulu lalu hash, tetapi itu akan gagal jika arsip rusak sebelum hash. Selain itu, Anda harus membacanya dan jika Anda mengerjakan banyak file dengan ukuran beberapa ratus GB, Anda akan tahu bahwa Anda benar-benar tidak ingin membacanya lagi jika tidak harus.

Jadi yang saya lakukan hanyalah ini:

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

Itu menciptakan bola tar dan pipa itu ke tee yang kemudian pipa itu ke dua sub-shell, di mana satu hash dan yang lain itu ditulis ke disk.

Ini juga bagus jika Anda ingin melakukan beberapa operasi pada file besar:

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

Membaca file sekali, hash (sehingga Anda dapat memeriksa apakah masih seperti seharusnya), mengekstraknya, dan menyalinnya ke lokasi yang berbeda. Tidak perlu membacanya tiga kali untuk itu.


3
Nitpick: teetidak membuat subkulit; shell panggilan berjalan sha5sumdan catdan menghubungkan output mereka ke file deskriptor yang diteruskan tee. Juga, penggunaan yang tidak berguna cat; Anda dapat menggunakan pengalihan input untuk teemembaca langsung dari file.tar.gz.
chepner

@ chepner Anda benar tentang kata seru pertama tetapi Anda benar-benar salah tentang kata seru kedua. Saya suka menulis saluran pipa saya secara berurutan, sehingga menunjukkan input di sebelah kanan sangat buruk untuk dibaca dan secara objektif jelas lebih rendah daripada metode saya dan sama sekali bukan preferensi subjektif saya. catApakah cinta. catadalah kehidupan.
UTF-8

6
Anda juga dapat menulis < file.tar.gz tee >(sha256sum) ...jika Anda khawatir tentang urutan leksikal dari pengalihan. Itu tidak mengubah fakta bahwa tidak perlu untuk proses yang sepenuhnya terpisah hanya untuk memberi makan satu file tee.
chepner

1
@ chepner Cool, terima kasih! Belajar sesuatu hari ini. :)
UTF-8

1
Biaya awal cat relatif rendah. Biaya tambahan 100 GiB panggilan sistem baca + baca pasti membuang waktu CPU dan bandwidth memori ekstra untuk contoh file besar yang Anda usulkan. Ingat bahwa bandwidth memori adalah sumber daya bersama di semua inti, belum lagi polusi tambahan dari cache L3 dari penyalinan itu. Pada x86 dengan mitigasi Specter + Meltdown diaktifkan, panggilan sistem lebih mahal daripada sebelumnya. Anda menggunakan jumlah waktu ekstra CPU yang terukur selama salinan itu. Juga >(cat > foo)tidak lebih mudah dipahami daripada foo, IMO.
Peter Cordes

12

Nitpick pada jawaban @ bertieb yang mengatakan Contoh ini menunjukkan tee digunakan untuk mem-bypass batasan bawaan pada perintah sudo. sudo tidak dapat menyalurkan output standar ke file.

Tidak ada batasan yang melekat, hanya kesalahpahaman tentang bagaimana perintah diproses.

Contoh:

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

The shell saat mem-parsing baris perintah. Ia menemukan pengalihan output dan melakukan itu. Kemudian ia mengeksekusi perintah, yang merupakan sudodan menyediakan baris perintah yang tersisa sebagai argumen untuk perintah yang dieksekusi. Jika shell saat ini tidak memiliki izin root, maka redirection output akan gagal.

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

Ini berfungsi karena redirection output ditangguhkan ke teeperintah, yang pada saat itu memang memiliki izin root karena dieksekusi melalui sudo.

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

Ini berfungsi karena shell yang melakukan pengalihan memiliki izin root.


2
Juga, Anda mungkin perlu sudountuk perintah itu, tetapi tidak untuk file yang menjadi output dan pengalihan berfungsi dengan baik:sudo foo-needs-privilege > /tmp/this-output-file-doesnt
Dennis Williamson

10

Seperti orang lain telah sebutkan, piping output ke teeperintah menulis bahwa output ke file dan stdout.

Saya sering menggunakan teeketika saya ingin menangkap output dari perintah yang membutuhkan waktu lama untuk dijalankan, sementara juga ingin memeriksa output secara visual saat perintah membuatnya tersedia. Dengan begitu, saya tidak harus menunggu perintah selesai berjalan sebelum saya memeriksa hasilnya.

Apa yang tampaknya belum disebutkan (kecuali saya melewatkannya), adalah bahwa teeperintah itu juga dapat menulis ke beberapa file sekaligus. Sebagai contoh:

ls *.png | tee a.txt b.txt

akan menulis semua *.pngfile dalam direktori saat ini ke dua file yang berbeda ( a.txtdan b.txt) sekaligus.

Bahkan, Anda dapat mengetik teks ke beberapa file berbeda sekaligus dengan teeseperti ini:

$ 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

9

Penggunaan tee yang paling umum adalah untuk melihat teks pada terminal pada saat yang sama saat Anda mengirimnya ke file (atau file). Kata-kata dari pertanyaan Anda menganggap Anda hanya pernah menulis teks ke file log. Saya memiliki skrip yang menulis daftar nama file atau nama direktori untuk memicu file (untuk diproses oleh skrip lain secara tidak serempak) dan saya menggunakan tee untuk mengirim konten yang sama ke stdout. Semua stdout diarahkan ke log. Jadi saya punya teks di mana saya inginkan dan saya memiliki catatan entri log yang saya lakukan ini, semua dari satu pernyataan 'gema'

tee juga merupakan metode terbaik di Unix untuk membuat banyak file yang identik. Saya menggunakannya sesekali untuk membuat beberapa file kosong, seperti ini ...

:|tee file01 file02 file03

5
mengapa tidak touch? (lebih jelas apa yang terjadi)
Attie

@ Attie touchtidak akan memotong file jika sudah ada tetapi hanya memperbarui stempel waktu dan membiarkan kontennya apa adanya; tetapi teeakan memotong mereka. Selain itu, melakukan rm+ touchberbeda dari tee(pikirkan tentang hardlink dan symlink)
Matija Nalis

Lalu mengapa tidak truncate -s 0? :-)
Attie

1

Bayangkan, Anda ingin menulis output dari suatu perintah ke file log DAN mencetak ke stdout. Ketika Anda perlu melakukannya pada saat yang sama, maka Anda perlu tee.

Kasus penggunaan adalah memiliki skrip build yang menulis keseluruhan build ke stdout (mis. Untuk Jenkins) tetapi hal-hal penting pada saat yang sama ke file log terpisah (untuk email ringkasan).

Anda akan benar-benar mulai hilang teeketika Anda harus skrip di Windows. Tidak ada teedan itu benar-benar menjengkelkan.


Bukankah itu sepele untuk dibuat?
Lightness Races in Orbit

Tidak dimungkinkan dengan batch / cmd karena Anda tidak dapat membagi aliran output dari perintah dengan mudah.
domih

Benar tapi seperti program C ++ tiga baris ...
Lightness Races in Orbit

1
Distribusi Windows unxutils memiliki banyak alat baris perintah Unix yang, tidak seperti beberapa distribusi, tidak mencemari lingkungan eksekusi Windows Anda. Keterbatasan terbesar adalah pada "glob" bing, yang bekerja secara berbeda pada Unix / Linux daripada pada Windows. "tee" adalah beberapa alat yang tersedia.
cmm

2
Jangan konyol, ini tahun 2018. Gunakan Powershell tee. Cmd tidak pernah dimaksudkan untuk skrip serius - itulah tujuan VBS. Powershell adalah alat skrip masuk baru. Memang, Cmd masih cukup kuat, tetapi alat baris perintah sangat sedikit.
Luaan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.