Яке призначення 'трійника'?


90

Усі звичаї, які teeя коли-небудь бачив, були такими:

 do_something | tee -a logfile

Або:

do_something_else | tee logfile

Є чи teeпридумано для тих , які не знають , що ви можете зробити те ж саме з оболонкою трубою перенаправлення? Як от:

do_something >> logfile

Або:

do_something_else > logfile

Це практично те саме, і для набору потрібне менше натискань клавіатури. Яких прихованих рис я не бачу tee?


62
Як на це не відповів перший рядок чоловічої сторінки "... і записувати до стандартного виводу та файлів" ? Відповіді цікаві, але в цілому розмова про те, наскільки корисні труби, просто підсилює те, як цей Q здається занадто широким, і, можливо, його слід було закрити.
Xen2050

3
@ Xen2050 Питання не можна звинувачувати у занадто широкій відповіді. Питання є дуже конкретним, як і зараз відповідь з найбільш високою оцінкою .
Джон Бентлі

1
@JonBentley питання не схоже на "конкретну проблему з достатньою деталізацією, щоб визначити адекватну відповідь" (як читається у близькому діалозі). Це звучить приблизно так: "якщо на ваше запитання можна відповісти цілою книгою, або є багато поважних відповідей (але жодного способу визначити, які - якщо такі є - правильні), це, мабуть, занадто широкий для нашого формату". (Джерело: Довідковий центр )
Xen2050

4
@ Xen2050 Чи читаємо ми те саме запитання? Мені це здається дуже специфічним - у чому різниця між трійником і трубами? На це було адекватно відповіді, використовуючи два речення. Далеко не ціла книга. Той факт, що деякі відповіді вирішують піти по дотичній, не має нічого спільного зі сферою питання.
Джон Бентлі

@JonBentley: Чи читаємо ми те саме запитання? R Moog доброї з роду- передбачає досить добре сфокусований питання - яка різниця між tee і I / O перенаправленням ?   Справа в тому , що він говорить , «оболонка труби перепризначення , такі як >і >>" не є крапкою в його користь, і є аргументом в користь закриття неясною. Але він насправді задає кілька запитань: "Яка мета tee?", " teeВинайдено для тих, хто не знає, що ви можете зробити те ж саме з перенаправленням оболонки?" Та "У яких прихованих функціях я не бачу tee?". Принаймні два з цих питань занадто широкі.
G-Man

Відповіді:


242

Те, що ви не бачите, - це do_something | tee -a logfileдодає висновок у logfile та stdout, а do_something >> logfileвкладає його лише у файл реєстрації.

Мета tee- створити сценарій з одним вхідним сигналом з декількома вихідними сигналами - подібно до перетину 'Т'

EDIT

Там були коментарі навколо того, як teeдає можливість більш безглузде використання sudo. Це поруч з точкою: cat, ddабо , може бути , краще bufferнадати цю можливість з більш високою продуктивністю, якщо ви не потрібні кілька виходів. Використовуйте teeдля того, що він призначений, а не для того, що він "також може зробити"


37
Багаторазовий вихід є ключовим. teeможна навіть приймати декілька аргументів і записувати у багато файлів одночасно.
Каміль Маціоровський

20
Я б назвав це штуцером трубопроводу , а не перехрестям (як у дорожньому перехресті?).
користувач20574

7
Як я можу використовувати 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не працює, тому що перенаправлення обробляється оболонкою non-sudo. Що стосується dd, echo /var/work/core.%p | sudo dd of=/proc/sys/kernel/core_patternпрацює, але ddчасто це перенапружений інструмент, здатний завдати великої шкоди, особливо під sudo. Щодо того buffer, його не встановлено за замовчуванням у жодному з дистрибутивів на базі RedHat або Ubuntu, які я маю передати (або MacOS) ...
Digital Trauma

3
@EugenRieck Я розумію, що відношення 1: n є основним функцією. Однак ні вбудований, catні /bin/catробота в мені в цій ситуації. Не має значення, звідки catпоходить - >все одно буде оброблятися оболонкою верхнього рівня (не-судо). Перевага teeза кадр catв цій ситуації є те , що вона дозволяє вихідний файл , який буде прийнята в якості командного рядка пар (а не перенаправляти). ddце, безумовно, життєздатний варіант, хоча я все-таки віддаю перевагу teeцьому
Digital Trauma

3
@EugenRieck Яка оболонка має catі teeяк вбудовані? І яка версія sudoможе запускати вбудовані оболонки?
wjandrea

118

Tee не марний

Може, ти це все-таки знав? Якщо ні, читайте далі! Або якщо ви знаєте, як це працює, але не знаєте, чому він існує, пропустіть до кінця, щоб побачити, як він вписується в філософію Unix.

Що це мета tee?

Найпростіше, він приймає дані на стандартний вхід і записує їх до стандартного виводу та одного (або більше) файлів. Це було подібне до сантехнічного трійника таким чином, як він розбиває один вхід на два виходи (і два напрямки).

Приклади

Візьмемо ваш перший приклад:

do_something | tee -a logfile

Це займає вихід do_somethingта додає його до журналу, а також відображає його користувачеві. Фактично, сторінка Вікіпедії на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"

Цей приклад показує, що трійник використовується для обходу властивого для sudoкоманди обмеження . sudoне в змозі передавати стандартний вихід у файл. Завантажуючи стандартний вихідний потік у /dev/null, ми також пригнічуємо дзеркальний вихід у консолі. Наведена вище команда надає поточному користувачеві доступ до сервера через ssh, встановивши відкритий ключ користувача до списку авторизації ключів сервера.

Чи, можливо, ви хочете взяти висновок однієї команди, написати це десь і також використовувати це як вхід до іншої команди?

Ви також можете використовувати команду tee для збереження результату команди у файл та перенаправлення того ж виходу, що і вхід до іншої команди.

Наступна команда візьме резервну копію записів crontab і передасть записи crontab як вхід до команди sed, яка зробить заміну. Після заміни він буде доданий як нове завдання cron.

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

(кредит на приклади використання команд Tee )

Tee працює з філософією Unix:

Пишіть програми, які роблять одне і роблять це добре. Напишіть програми для спільної роботи. Пишіть програми для обробки текстових потоків, тому що це універсальний інтерфейс.

(Кредит до основ філософії Unix )

tee відповідає всім цим:

  • це робить одне: створює додаткову копію введення
  • він працює з іншими програмами, тому що саме клей (або сантехнічний шматок "T", якщо вам зручніше) дозволяє іншим програмам працювати разом, як у наведених вище прикладах
  • це робиться шляхом маніпулювання текстовим потоком, поданим на стандартному вході

3
@Joe: sudo tee -aце , ймовірно, більш недавнє нововведення (я вперше побачив його в посібниках Ubuntu / вікі спеціально для установки речі в /proc/sys, тому що перехід на Ubuntu, коли я перейшов на sudoсистему , засновану (як Ubuntu налаштованому за замовчуванням) замість використання suз root пароль). Я вважаю , що це teeпопередньо sudo, тому це не є підставою для teeіснування. Вам не потрібно teeдля цього, це просто коротше, щоб вводити інтерактивно, ніж sudo sh -c 'cat > output'.
Пітер Кордес

1
Із сучасними снарядами, як баш, ви можете teeживити два трубопроводи, як foo | tee >(pipe2) | pipe1. Або ще одне цікаве - ffmpeg ... |& tee /dev/tty | sed 's/.*\r// > encode.logінтерактивно бачити оновлення рядків стану на tty, видаляючи при цьому "рядки", які закінчуються поверненням каретки замість нового рядка для фактичного ведення журналу. (тобто відфільтруйте оновлення рядка стану). Загалом, ви можете наклеїти tee /dev/ttyбудь-де в конвеєрі як налагодження друку.
Пітер Кордес

2
Це менше обмеження судо, над яким ви працюєте, і більше обмеження інтерпретації оболонки>. Коли ви запускаєте команду з sudo, її stdout надсилається назад до вашої програми оболонки, а подальші переадресації з> запускаються з дозволами оболонки. Якщо ви хочете писати з підвищеними дозволами, вам потрібно, щоб піднята частина трубопроводу була такою, що робить написання. Існує велика кількість способів зробити це залежно від того, на який саме ефект ви збираєтеся. Якщо ви дійсно хочете використовувати> щось на кшталт "sudo bash -c" команда> outfile "'зробить цю роботу.
Перкінс

Точно, @Perkins. Оболонка аналізує >та встановлює перенаправлення до того, як sudo навіть отримає exec"d", тому судо це точно не обмеження тим, що він не обробляє речі, які ніколи не бачить. :) Я зазвичай намагаюся позначати це як "робочий процес судо" або якийсь подібний термін, коли я це пояснюю, а не описую сам судо.
dannysauer

sudo tee -aІМХО - це зловживання трійником. Використовуйте sudo cat, sudo ddабо (з найкращою продуктивністю у багатьох випадках), sudo bufferякщо вам не потрібно декілька виходів.
Євген Рік

70

Це практично те саме, і для набору потрібні менше ударів клавіатури.

Це зовсім не те саме ...

Наведене нижче виглядає дещо еквівалентним, але це не так:

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

Критична відмінність полягає в тому, що перший записав дані тільки в названий файл, а другий записав hiу термінал ( stdout) та названий файл, як показано нижче:

переадресація проти трійника


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 )

2
Не забудьте exec > >(tee "$LOGFILE") 2>&1в bash-скрипті, який дозволяє скрипту виводити stdout і stderr обом, stdout і файлу, на який вказує $LOGFILE.
rexkogitans

@rexkogitans 2> & 1 - це не синтаксис пакетного пакету cmd?
dmb

@dmb: це синтаксис оболонки для "відправити stderr (= 2) на те саме місце, що і stdout (= 1)"
psmears

@rexkogitans Це було справді справедливим питанням, я не можу насправді знати, що ти не використовував "Windoze" протягом десяти років. Я використовую 2>&1для падіння виводу та помилки з txt файлами у Windows.
dmb

1
@dmb Мені шкода за грубі звуки. Вся справа в коментарі psmears. Очевидно, що тут Windows прийняв стиль Unix.
rexkogitans

27

Це трійник:
введіть тут опис зображення

Т-подібний трубопровід. Він має впускний отвір і дві окремі розетки.
Іншими словами, вона розбиває одну трубу на дві; як вила в дорозі.

Аналогічно, teeце труба ( |), яка дозволяє перенаправляти стандартний вхід на два окремі виходи.


Приклад
Скажіть, наприклад, ви вводите ls /.
Ви отримаєте вихід, який виглядає приблизно так:

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

Перенаправляйте вихід на текстовий файл, ls / > ls.txtі жоден вихід не відображається в оболонці, тільки в текстовому файлі, що виходить.

Хочете побачити вихід і одночасно передати його текстовому файлу?
Додайте teeдо своєї труби ( |), тобто:ls / | tee ls.txt


Порівняйте два:

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

4
+1 для картини, яка, як ми знаємо, варто тисячу слів
Сергій Колодяжний,

Якби ви вибрали твір садового шланга, ви б відповідали оригінальній метафорі Дуга Макілроя.
JdeBP

@JdeBP Вибачте, я не маю уявлення, хто це. Він оригінальний автор утиліти чи щось таке? Потік даних та фізичний електричний струм часто порівнюють з гідравлічними системами, але ви, мабуть, це знаєте. У всякому разі, я просто вибрав цей стиль, щоб він був дуже простим. Я насправді збирався це зробити, щоб ознайомити його, але садовий сорт, як правило, має більше Y-форми та / або візуально складні кріплення для кріплення аксесуарів тощо. Хоча це, по суті, те саме.
голоси


18

Ні. Ви випадково згадуєте один з небагатьох прикладів, коли ви дійсно можете перенаправляти файли >та >>оператори.

Але Трій може зробити набагато більше. Оскільки ви трубитесь до нього, то можете передати щось інше.

Хороший приклад наведено на сторінці вікіпедії :

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

В основному, ви можете підключити трубку до трійника, тож ви зможете перейти від трійника до чогось іншого. Якщо все, що ви хочете зробити, це написати файл журналу, так, тоді вам не дуже потрібен Tee.


17

teeдалеко не марний. Я користуюся ним постійно і радий, що він існує. Це дуже корисний інструмент, якщо у вас є трубопровід, який ви хочете розколоти. Дуже простий приклад - це те, що у вас є деякий каталог, $dякий ви хочете націлити, і ви також хочете його хеш, тому що ви параноїк (як я) і не довіряєте носії інформації, щоб надійно зберігати дані. Ви можете спершу записати його на диск, а потім зафіксувати хеш, але це не вдасться, якщо архів буде пошкоджений до його хешування. Крім того, вам доведеться прочитати його, і якщо ви працюєте над файлами розміром декілька сотень ГБ, ви знаєте, що дійсно не хочете читати їх знову, якщо цього не потрібно.

Тож, що я роблю, це просто таке:

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

Він створює куля дьогтю і трубить його до трійника, який потім передає його в дві підкорпушки, в одній з яких він хеширується, а в іншій записується на диск.

Також чудово, якщо ви хочете виконати кілька операцій над великим файлом:

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

Прочитає файл один раз, хеширує його (щоб ви могли перевірити, чи він як і раніше є), витягує його та копіює в інше місце. Для цього не потрібно її читати тричі.


3
Nitpick: teeне створює підшарів ; оболонка виклику працює sha5sumі catпідключає свій вихід до дескрипторів файлів, які передаються tee. Також марне використання cat; ви можете використовувати переадресацію вводу для teeчитання безпосередньо з file.tar.gz.
чепнер

@chepner Ви маєте рацію щодо першого заклинку, але ви абсолютно помиляєтесь щодо другого. Мені подобається писати свої трубопроводи в порядку, тому позначення введення справа жахливо для читабельності, і це явно об'єктивно поступається моєму методу і зовсім не є моїм суб'єктивним уподобанням. catце кохання. catце життя.
UTF-8,

6
Ви також можете написати, < file.tar.gz tee >(sha256sum) ...якщо вас турбує лексичне впорядкування переадресацій. Це не змінює того факту, що немає необхідності в абсолютно окремому процесі, щоб просто подати один файл tee.
чепнер

1
@chepner Класно, дякую! Навчився чогось сьогодні. :)
UTF-8,

1
Вартість старту cat порівняно невисока. Вартість додаткових 100 Гбіт системних дзвінків запису + читання безумовно витрачає зайвий час процесора та пропускну здатність пам’яті для запропонованого вами прикладу величезного файлу. Пам'ятайте, що пропускна здатність пам'яті - це спільний ресурс для всіх ядер, не кажучи вже про додаткове забруднення кешу L3 від цього копіювання. На x86 з увімкненою функцією зменшення спектру Spectre + Meltdown системні дзвінки дорожчі, ніж раніше. Ви використовуєте вимірювану кількість додаткового часу процесора протягом цієї копії. Також >(cat > foo)не простіше зрозуміти, ніж fooІМО.
Пітер Кордес

12

Відповідь Нітпіка на @ bertieb Цей приклад показує, що трійник використовується для обходу властивого обмеження команди sudo. sudo не в змозі передавати стандартний вихід у файл.

Немає притаманного обмеження, лише непорозуміння способу обробки команди.

Приклад:

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

Поточна оболонка розбирає командний рядок. Він знаходить перенаправлення виводу і виконує це. Потім він виконує команду, яка є sudoі надає решту командного рядка як аргументи виконаній команді. Якщо поточна оболонка не має кореневих дозволів, перенаправлення виводу буде невдалим.

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

Це працює, тому що перенаправлення виводу відкладено для teeкоманди, яка в цьому пункті має кореневі дозволи, оскільки вона виконувалася через sudo.

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

Це працює, оскільки оболонка, яка виконує перенаправлення, має кореневі дозволи.


2
Також вам може знадобитися sudoкоманда, але не для виведення файлу, і перенаправлення працює чудово:sudo foo-needs-privilege > /tmp/this-output-file-doesnt
Денніс Вільямсон,

10

Як вже згадували інші люди, трубопровідний вихід у teeкоманду пише, що вихід і у файл, і у stdout.

Я часто використовую, teeколи хочу захопити вихід з команди, яка запускає тривалий час, а також хочу візуально перевірити вихід, коли команда робить його доступним. Таким чином, мені не потрібно чекати, коли команда закінчить виконання, перш ніж я перевіряю вихід.

Що, здається, ще не було згадано (якщо я цього не пропустив), це те, що teeкоманда також може записувати в кілька файлів одночасно. Наприклад:

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

випише всі *.pngфайли в поточному каталозі до двох різних файлів ( a.txtі b.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

9

Найбільш поширене використання трійника - це перегляд тексту на терміналі одночасно з надсиланням його до файлу (або файлів). Формулювання вашого запитання передбачає, що ви коли-небудь пишете текст у логіни. У мене є скрипти, які записують списки імен файлів або імен для запуску файлів (обробляються іншими сценаріями асинхронно), і я використовую tee для того, щоб надсилати той же вміст в stdout. Весь stdout спрямований до колод. Тож у мене є текст, де я цього хочу, і у мене є запис запису в журналі, що я це робив, все з одного твердження "ехо"

Трійник - це також найкращий метод в Unix для створення декількох однакових файлів. Я використовую його час від часу для створення кількох порожніх файлів, як цей ...

:|tee file01 file02 file03

5
чому ні touch? (більше відразу очевидно, що відбувається)
Attie

@Attie touchне буде обрізати файли, якщо вони вже існують, а лише оновить свої часові позначки та залишить їх вміст таким, який є; але teeобріже їх. Крім того, робити rm+ touchінше, ніж tee(подумайте про жорсткі посилання та посилання)
Matija Nalis

Тоді чому б і ні truncate -s 0? :-)
Attie

1

Уявіть, ви хочете записати вихід команди в файл журналу І надрукувати в stdout. Коли вам потрібно це робити одночасно, тоді вам це потрібно tee.

Випадок використання - це створення сценаріїв збірки, які записують всю збірку до stdout (наприклад, для Jenkins), але важливі речі при цьому в окремий файл журналу (для коротких електронних листів).

Ви дійсно почнете бракувати, teeколи вам доведеться сценарій у Windows. Немає teeі це насправді дратує.


Хіба це не банально творити?
Гонки легкості на орбіті

З batch / cmd це неможливо, оскільки ви не можете легко розділити потік виводу з команди.
domih

Правильно, але як трирядна програма C ++ ...
Гонки легкості в орбіті

1
У дистрибутиві Windows unxutils є багато інструментів командного рядка Unix, які, на відміну від деяких дистрибутивів, не забруднюють ваше середовище виконання Windows. Найбільше обмеження стосується "глобального" бінгу, який працює на Unix / Linux інакше, ніж у Windows. "Трійник" є серед доступних інструментів.
смм

2
Не будь дурним, це 2018 рік. Використовуй Powershell, так і є tee. Cmd ніколи не призначався для серйозних сценаріїв - саме для цього VBS. Powershell - це новий інструмент сценаріїв, що переходить до програми. Зрозуміло, Cmd все ще досить потужний, але інструментів командного рядка досить мало.
Луань
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.