Как я могу сжать стандарт в файл, а также распечатать стандарт в стандарте?

Я хочу выполнить команду, получить вывод этой команды с помощью gzip на лету, а также вывести вывод этой команды.

то есть что-то вроде:

echo "hey hey, we're the monkees" | gzip --stdout > my_log.gz

За исключением случаев, когда строка выполняется, я хочу видеть это на стандартном выходе:

hey hey, we're the monkees

person Ross Rogers    schedule 20.02.2009    source источник


Ответы (4)


echo "hey hey, we're the monkees" | tee /dev/tty | gzip --stdout > my_log.gz

Как указано в комментариях, в некоторых случаях /dev/stdout может работать лучше, чем /dev/tty.

person Paul Tomblin    schedule 20.02.2009
comment
Что там делает /dev/tty? Исходный вопрос требовал вывода на стандартный вывод, а не обязательно на терминал. - person Gareth Rees; 20.02.2009
comment
/dev/tty — это синоним текущего терминала. Спрашивающий использовал стандартный выход в обычной манере для обозначения текущего терминала, а не более строгое определение термина. - person Paul Tomblin; 20.02.2009
comment
Если бы действительно было принято использовать стандартный вывод для обозначения текущего терминала, то это был бы обычай, который мог бы привести к большой путанице! Для этого вопроса в bash есть /dev/stdout. - person Gareth Rees; 21.02.2009
comment
При каких обстоятельствах /dev/tty не даст желаемого результата, а /dev/stdout даст? - person Paul Tomblin; 21.02.2009
comment
Когда стандартный вывод идет в файл, а не в терминал. - person Gareth Rees; 26.02.2009
comment
Это просто не то, о чем просили - то, что просили, было конвейером оболочки, который отправлял бы вывод на его stdout И сжимал его в файл. (Что, если я хочу отправить вывод еще одной программе, скажем, less(1). - person SamB; 27.04.2010
comment
/dev/stdout не работал в Solaris 10 с использованием KSH, а /dev/tty работал. - person Tom Purl; 27.05.2011
comment
/dev/stdout ни в коем случае не будет работать, так как он применяется после символа |. - person Joshua; 26.04.2014
comment
@GarethRees, вы правы, но практичность побеждает чистоту, если вы используете python -m this. вы могли бы служить публике, указав на это в ответе - в отличие от редактирования вопроса, который скрыл бы тот факт, что обычай, возможно, является обычным явлением. - person n611x007; 27.10.2015

Другой способ (предполагая оболочку типа bash или zsh):

echo "hey hey, we're the monkees" | tee >(gzip --stdout > my_log.gz)

По общему признанию странный синтаксис >() в основном делает следующее:

  • Создать новый FIFO (обычно что-то в /tmp/)
  • Выполните команду внутри () и привяжите FIFO к стандартному вводу этой подкоманды
  • Вернуть имя файла FIFO в командную строку.

То, что tee в конечном итоге видит, выглядит примерно так:

tee /tmp/arjhaiX4

Все, что видит gzip, это его стандартный ввод.

Подробнее о Bash см. man bash. Он находится в разделе перенаправления. Для Zsh см. man zshexpn под заголовком "Подстановка процессов".

Насколько я могу судить, оболочка Korn, варианты классической оболочки Bourne (включая ash и dash) и оболочка C не поддерживают этот синтаксис.

person greyfade    schedule 20.02.2009
comment
Круто, я сам кое-чему здесь учусь. Можно поподробнее, что там происходит? - person Paul Dixon; 20.02.2009
comment
если я правильно понял, вместо того, чтобы дать файл для тройника, он отправляет копию в качестве входных данных для выражения в квадратных скобках, которое записывает вывод gzip в другой файл. Несжатые данные оставляют tee как обычно на стандартном выводе. - person Paul Dixon; 20.02.2009
comment
спасибо за редактирование, ценю дополнительную информацию! Никогда не знал об этом синтаксисе FIFO. - person Paul Dixon; 20.02.2009
comment
Это стало для меня шоком, когда я впервые узнал об этом. Но это позволяет обойтись без очень сложных перенаправлений, когда несколько программ работают с одним и тем же входом одновременно. Конечно, вы также можете сделать mkfifo вручную и запустить все эти команды в разных консолях, если вам нужно. - person greyfade; 20.02.2009
comment
Я работаю с Unix уже 20 лет и еще не освоил этот новый синтаксис. - person Paul Tomblin; 20.02.2009
comment
Я использую это для регистрации. Я нашел много буферов gzip, и когда я нажимаю Ctrl-C, я теряю все. Игнорирование SIGINT с помощью >(trap '' INT; gzip --stdout > my_log.gz), похоже, сохраняет его. - person jozxyqk; 16.05.2019

Приятного чаепития ти!

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

Поскольку у меня медленный день, вот несколько великолепных иллюстративных ascii-артов...

           +-----+                   +---+                  +-----+  
stdin ->   |cmd 1|    -> stdout ->   |tee|   ->  stdout  -> |cmd 2|
           +-----+                   +---+                  +-----+
                                       |
                                       v
                                     file

Как показывает greyfade в другом ответе, «файл» не обязательно должен быть обычным файлом, но может быть FIFO, позволяющим направить вывод этого тройника в третью команду.

           +-----+                   +---+                  +-----+  
stdin ->   |cmd 1|    -> stdout ->   |tee|   ->  stdout  -> |cmd 2|
           +-----+                   +---+                  +-----+
                                       |
                                       v
                                     FIFO
                                       |
                                       v
                                    +-----+
                                    |cmd 3|
                                    +-----+
person Paul Dixon    schedule 20.02.2009
comment
Но я хочу сжать промежуточный файл на лету. Это возможно только с помощью тройника? - person Ross Rogers; 20.02.2009
comment
да, другой Пол написал хороший краткий ответ, пока я возился с диаграммой ascii art :) - person Paul Dixon; 20.02.2009
comment
:-P Я знаком с tee'ing в файл, как вы описываете. Я просто не знаю, как сжать этот файл. если я делаю эхо foo | tee bar.log, я не знаю, как сделать tee gzip 'bar.log', кроме решения, опубликованного Полом Томблином. - person Ross Rogers; 20.02.2009
comment
чувак, stackoverflow — это круто. Мне даже не пришлось беспокоить гуру офисного Linux. Спасибо всем. - person Ross Rogers; 20.02.2009
comment
Отличный ответ greyfade показывает, как вы можете делать то, что хотите, с выводом tee'd. - person Paul Dixon; 20.02.2009
comment
Да, ответ Grayfade делает именно то, что предлагает этот, но с очень кратким синтаксисом. Эти cmd 3 там написано >(cmd 3). - person SamB; 27.04.2010

Просто чтобы опубликовать способ, который не требует прикосновения к диску:

echo "hey hey, we're the monkees" | (exec 1>&3 && tee /proc/self/fd/3 | gzip --stdout > my_log.gz)
person Joshua    schedule 04.01.2010
comment
Что, вы имеете в виду, что /tmp находится на диске?!?!?!? - person SamB; 27.04.2010
comment
С точки зрения безопасности так и есть. - person Joshua; 27.04.2010