Какова цель "тройник"?

Все обычаи tee Я когда-либо видел такие:

 do_something | tee -a logfile

Или же:

do_something_else | tee logfile

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

do_something >> logfile

Или же:

do_something_else > logfile

Это практически то же самое, и для набора текста требуется меньше нажатий клавиш. Какие скрытые функции я не вижу в tee?

10 ответов

Чего ты не видишь? do_something | tee -a logfile помещает вывод в logfile и в стандартный do_something >> logfile помещает это только в файл журнала.

Цель tee заключается в создании сценария с одним входом и несколькими выходами - как при пересечении "Т".

РЕДАКТИРОВАТЬ

Там были комментарии о том, как tee позволяет более простое использование sudo, Это не относится к делу: cat, dd или может быть лучше buffer предоставьте эту возможность с лучшей производительностью, если вам не нужны несколько выходов. использование tee за то, что он предназначен, а не за то, что он "может сделать"

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 Мы также подавляем зеркальный вывод в консоли. Приведенная выше команда предоставляет текущему пользователю root доступ к серверу через ssh, установив открытый ключ пользователя в список авторизации ключей сервера.

Или, может быть, вы хотите взять выходные данные одной команды, записать их где-нибудь, а также использовать их в качестве входных данных для другой команды?

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

Следующая команда создаст резервную копию записей crontab и передаст записи crontab в качестве команды ввода в sed, которая выполнит замену. После замены он будет добавлен в качестве нового задания cron.

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

(благодарю за примеры использования команды Tee)

Tee работает с философией Unix:

Напишите программы, которые делают одно и делают это хорошо. Напишите программы для совместной работы. Написание программ для обработки текстовых потоков, потому что это универсальный интерфейс.

(Благодарность основам философии Unix)

tee подходит всем этим:

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

Это практически то же самое, и для набора текста требуется меньше нажатий клавиш.

Это совсем не то же самое...

Следующее представляется несколько эквивалентным, но это не так:

$ 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 )

Это тройник:

Т-образный фитинг. Он имеет вход и два отдельных выхода.
Другими словами, он разделяет одну трубу на две; как развилка на дороге.

Так же, 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

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

Но Ти может сделать гораздо больше. Поскольку вы направляетесь к нему по трубопроводу, вы можете затем передавать по трубопроводу что-то еще.

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

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

По сути, вы можете передавать по трубопроводу к Tee, а затем по трубопроводу от Tee к чему-то еще. Если все, что вы хотите сделать, это написать файл журнала, да, тогда вам не нужен Tee.

tee далеко не бесполезен. Я использую это все время и рад, что это существует. Это очень полезный инструмент, если у вас есть конвейер, который вы хотите разделить. Очень простой пример - у вас есть каталог $d что вы хотите использовать tar, а также хотите его хешировать, потому что вы параноик (как и я) и не доверяете носителю для надежного хранения данных. Вы можете сначала записать его на диск, а затем хэшировать, но это не получится, если архив будет поврежден до того, как будет хеширован. Кроме того, вам придется прочитать его, и если вы будете много работать с файлами размером в несколько сотен ГБ, вы поймете, что действительно не хотите читать их снова, если этого не требуется.

Так что я делаю просто так:

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

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

Nitpick в ответе @bertieb, который гласит: В этом примере показано, как тройник используется для обхода врожденного ограничения в команде sudo. sudo не может передать стандартный вывод в файл.

Не существует внутренних ограничений, только неправильное понимание того, как обрабатывается команда.

Пример:

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

Текущая оболочка анализирует командную строку. Он находит перенаправление вывода и выполняет это. Затем он выполняет команду, которая является sudo и предоставляет оставшуюся командную строку в качестве аргументов для выполняемой команды. Если текущая оболочка не имеет прав доступа 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"

Это работает, потому что у оболочки, выполняющей перенаправление, есть права root.

Как уже упоминали другие люди, трубопроводная продукция к tee Команда записывает этот вывод как в файл, так и в стандартный вывод.

Я часто использую 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

Наиболее распространенное использование tee - видеть текст на терминале одновременно с отправкой его в файл (или файлы). Формулировка вашего вопроса предполагает, что вы когда-либо пишете текст в лог-файлы. У меня есть сценарии, которые пишут списки имен файлов или каталогов для запуска файлов (для асинхронной обработки другими сценариями), и я использую tee для отправки того же контента на стандартный вывод. Весь stdout направлен на логи. Итак, у меня есть текст, где я хочу, и у меня есть запись в журнале, в которой я это сделал, все из одного утверждения 'echo'

Это также лучший метод в Unix для создания нескольких одинаковых файлов. Я иногда использую его для создания нескольких пустых файлов, как это...

:|tee file01 file02 file03

Представьте, что вы хотите записать вывод команды в файл журнала и распечатать на стандартный вывод. Когда вам нужно сделать это одновременно, тогда вам нужно tee,

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

Вы действительно начнете скучать tee когда вам нужно сценарий в Windows. Здесь нет tee и это действительно раздражает.

Другие вопросы по тегам