Як прокладати трубопровідник без трубопроводу


24

Як з'єднати стандартний потік помилок, не прокладаючи стандартний потік?

Я знаю, що ця команда працює, але вона також виписує стандарт.

Command 2>&1 | tee -a $LOG

Як я можу отримати лише стандартну помилку?

Примітка. Я хочу з цього просто написати потік stderr в журнал і записати і stderr, і stdout на консоль.

Відповіді:


26

Для цього використовуйте один додатковий дескриптор файлів для переключення stderr та stdout:

find /var/log 3>&1 1>&2 2>&3 | tee foo.file

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

3>&1 Створює новий дескриптор файлу, 3, дублікат (копію) fd 1 (stdout).

1>&2 Зробіть stdout (1) дублікатом fd 2 (stderr)

2>&3 Зробіть fd 2, дублікат (копію) з 3, який раніше був зроблений копією stdout.

Тож тепер перемикаються stderr і stdout.

| tee foo.file tee дублює дескриптор файлу 1, який був перетворений в stderr.


Ой, не тестується на ksh, працює з bash, хоча ...
Kyle Brandt

Дякую, працює і в ksh. Я думаю, що більшість речей із труб та потоків є стандартними стандартами.
C. Ross

"Копіювати" насправді не правильно - Дивіться відповідь @ Гуаскеньо.
Кайл Брандт

Це також працює у Windows із tee.exeвстановленим :)
Acorn

13

Команда Unix / Linux Kyle виконує завдання перемикання STDERR з STDOUT; проте пояснення не зовсім правильне. Оператори переадресації не роблять жодного копіювання чи копіювання, вони просто перенаправляють потік в інший бік.

Переписання команди Кайла тимчасовим переміщенням 3> і 1 до кінця полегшило б розуміння поняття:

find /var/log  1>&2  2>&3  3>&1  

Написаний таким чином, Linux буде відображати помилку, оскільки & 3 ще не існує, оскільки вона розташована перед 3> & 1. 3> щось є способом оголосити (визначити), що ми будемо використовувати третю трубу, тому вона повинна бути розташована перед тим, як потрапляти воду в цю трубу, наприклад так, як написав її Кайл. Спробуйте цей інший спосіб просто для розваги:

((echo "STD1";  anyerror "bbbb"; echo "STD2" ) 3>&1 4>&2 1>&4 2>&3) > newSTDOUT 2> newSTDERR

Прикро не мати способу робити копії. Ви не можете робити такі речі, як "3> & 1 3> & 2" в одній команді, оскільки Linux буде використовувати лише перший знайдений, а другий відхиляє.

Я ще не знайшов способу надіслати як помилку, так і звичайний вихід у файл, а також надіслати копію помилки на стандартний вихід однією командою. Для instace, у мене є робота з cron, що я хочу, щоб обидва виходи (помилка та стандарт) перейшли до файлу журналу, і помилка також вийде, щоб зробити повідомлення електронною поштою, відправлене моєму BlackBerry. Я можу це зробити двома командами за допомогою "tee", але помилка не відображається в правильному порядку серед звичайного рядка виводу у файлі. Це некрасивий спосіб вирішення проблеми:

((echo "STD1"; sdfr "bbbb"; echo "STD2" ) 3>&1 1>&2 2>&3 | tee -a log1 ) 2>> log1

Зауважте, що я повинен використовувати log1 двічі, і я повинен додати в обох випадках, як перший, який використовує параметр "-a" для команди "tee", а другий - ">>".

Роблячи котячий журнал1, ви отримуєте наступне:

STD1
STD2
-bash: sdfr: command not found

Зауважте, що помилка не відображається у другому рядку як слід.


Дивовижна корекція!
Кайл Брандт

Перевірте zsh та mult_iosпараметр (увімкнено за замовчуванням), щоб мати можливість перенаправляти FD кілька разів.
Том Хейл

2

відповідно до сторінки man для ksh (pdksh), ви можете просто зробити:

Команда 2> & 1> / dev / null | кіт -н

тобто дублювати stderr на stdout, перенаправляти stdout в / dev / null, а потім передавати в 'cat -n'

працює на pdksh в моїй системі:

$ errorecho () {echo "$ @"> & 2;}

$ errorecho foo
foo

$ errorecho foo> / dev / null # все одно має відображатися навіть із перенаправленням stdout
foo

$ errorecho foo 2> & 1> / dev / null | кіт -н
     1 foo
$   

Працює і з BusyBox
Udo G

1

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

(echo "foo" 3>&1 1>&2 2>&3 | tee -a log1 ) 2>> log1 >> log2

тоді як log1 записує stdout і stderr, а log2 записує лише stderr, і нічого іншого він не виводить на екран.

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