tar на трубу, але зберігайте -v багатослівний вихід окремо від STDERR


12

Звичайна команда tar

tar cvf foo.tar ./foo >foo.out 2>foo.err

має три вихідні потоки вводу-виводу

  • архівні дані до foo.tar
  • список імен файлів до STDOUT (переспрямовано у foo.out)
  • повідомлення про помилку до STDERR (переспрямовано у foo.err)

Тоді я можу перевірити foo.err на предмет повідомлень про помилки без необхідності читати список імен файлів.

якщо я хочу щось зробити з архівними даними (передавати їх через netcat або спеціальну програму стиснення), я можу використовувати -f -варіант tar таким чином

tar cvf - ./foo 2>foo.err | squish > foo.tar.S

Але тепер мій список файлів змішується з моїми повідомленнями про помилки, оскільки -vвихід tar, очевидно, не може перейти до STDOUT (саме там надходять дані архіву), тому tar начебто вміло пише це в STDERR.

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


Ви знайомі tee? Це здається досить вагомим випадком використання для цього.
HalosGhost

Відповіді:


9

Якщо ваша система підтримує /dev/fd/n:

tar cvf /dev/fd/3 ./foo 3>&1 > foo.out 2>foo.err | squish > foo.tar.S

Що з AT&T реалізацій ksh(або bashабо zsh) ви могли б написати, використовуючи підстановку процесу :

tar cvf >(squish > foo.tar.S) ./foo > foo.out 2>foo.err

Це робить саме те саме, за винятком того, що цього разу оболонка вирішує, який дескриптор файлів використовувати замість 3(як правило, вище 9). Ще одна відмінність полягає в тому, що цього разу ви отримаєте статус виходу tarзамість squish. У системах, які не підтримують /dev/fd/n, деякі оболонки можуть вдатися до названих труб для цієї функції.

Якщо ваша система не підтримує /dev/fd/nабо ваша оболонка не може використовувати названі труби для її заміни, то тут вам доведеться вручну мати справу з названими трубами .


6

Для цього потрібно використовувати названу трубу.

Спочатку створіть його в папці:

mkfifo foo.pipe

Потім використовуйте цю команду:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & cat foo.pipe >foo.tar

Примітка:cat -частина, тепер може бути gzipабо будь-який інший , який може читати з труби:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & gzip -c foo.pipe >foo.tar

Пояснення:

Висновок записується на ім'я труби ( foo.pipe), де інший proccess ( cat, gzip, netcat) зчитує інформацію з. Таким чином, ви не втрачаєте канали stdout / stderr для інформації.


1
Можливо, варто відзначити наслідки використання названих труб. 1) найкраще встановити umask 077(або використовувати приватний темп-дир) для запобігання читання або запису до нього інших процесів (у багатьох системах названі труби, як і інші файли створені за замовчуванням, які читаються у світі) названа труба використовується лише кожним екземпляром вашого сценарію (знову ж таки допомагає разовий приватний тимчасовий каталог) 3) Це означає, що вам потрібно буде після цього очистити або перервати його.
Стефан Шазелас

1
+1 - мені подобається ця відповідь. На жаль для мене, в моїй (старій) системі є деяка дивність у названих трубах, що робить їх ненадійними, коли я намагаюся це зробити.
RedGrittyBrick

1
@ StéphaneChazelas - Я думаю, що іноді може бути простіше прибрати спочатку, як-от:p="/tmp/pipe$$"; mkfifo "$p"; (read na; cmd[s]...) <>"$p" & (echo;rm "$p"; cmd[s]...) >"$p"
mikeserv

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.