Как я могу gzip стандарт в файл, а также распечатать стандарт в стандартный выход? - PullRequest
30 голосов
/ 20 февраля 2009

Я хочу выполнить команду, получить выходные данные этой команды, получить gzip'd на лету, а также отобразить вывод этой команды.

т.е. что-то вроде:

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

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

hey hey, we're the monkees

Ответы [ 4 ]

54 голосов
/ 20 февраля 2009

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

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

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

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

То, что tee в конечном итоге видит, это что-то вроде:

tee /tmp/arjhaiX4

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

Для Bash см. man bash для деталей. Это в разделе перенаправление . Для Zsh см. man zshexpn под заголовком «Замена процесса».

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

46 голосов
/ 20 февраля 2009
echo "hey hey, we're the monkees" | tee /dev/tty | gzip --stdout > my_log.gz

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

18 голосов
/ 20 февраля 2009

Хорошей чашки тройник !

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

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

           +-----+                   +---+                  +-----+  
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|
                                    +-----+
6 голосов
/ 05 января 2010

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

echo "hey hey, we're the monkees" | (exec 1>&3 && tee /proc/self/fd/3 | gzip --stdout > my_log.gz)
...