Перенаправить stderr в файл, но создать, только если произошел какой-либо stderr?

У меня есть команда вроде:

parallel --spreadstdin --line-buffered 'some_command 2> `mktemp --tmpdir /tmp/stderr`' | do_something 

Фокус в том, что parallel создает много процессов, и все они получают файл stderr, большинство из которых неинтересны, потому что они пустые. Как я могу заставить свою оболочку генерировать файл stderr только в том случае, если какой-либо стандартный вывод ошибки действительно произошел?

Насколько я знаю, это невозможно. Оболочка читается справа налево, поэтому, если существует 2> error . будет создан файл error . Я не думаю, что это возможно.

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

 tmp=$(mktemp); command 2> "$tmp"; [ -s "$tmp" ] && cp "$tmp" /path/to/log/files 

parallel –spreadstdin –line-buffered 'some_command 2 \

mktemp --tmpdir /tmp/stderr '| do_something && if [test -s / tmp / stderr]; тогда; сон .1; еще; rm / tmp / stderr

  • One-Liner для проверки наличия файлов и их размера больше нуля для TRUE; пустой, если FALSE.

IT – это то, что работает. Остановите подсчет своих битов и байтов и создайте триггер inotifywait при запуске, чтобы проверить ваши журналы, если они пустые, записать результаты в datatable и стереть журнал; затем запрограммируйте веб-интерфейс, который отправит вам сообщения по электронной почте, когда ключевые слова появятся в вашем журнале ошибок.

 while: do inotifywait -e create /tmp/* && \ if [ -s /tmp/stderr ] then ##put it in a datatable ##remove the log fi done 

iNotifyWait также может контролировать подсистему Kernel F / S, чтобы увидеть, был ли файл изменен, если вы добавляете. В противном случае измените исходный код и перекомпилируйте, чтобы предотвратить создание ошибки, изменив раздел try () catch () или отчета об ошибках (часть, которая выводит коды ошибок на экран).

Удивительно, насколько близко ответ на этот другой вопрос на SO пришел, чтобы ответить на вопрос, не поразив этого. Определите функцию оболочки (или напишите сценарий) следующим образом:

 save_err() { # Check that "$1" is set and either complain/abort or generate a default. if read -rx then { printf "%s\n" "$x"; cat; } > "$1" fi } 

Затем используйте как:

 some_command 2> >( save_err $(mktemp --tmpdir /tmp/stderr) ) 

Предостережения. Это приведет к сбою, если вывод stderr – это одна строка, не заканчивающаяся символом новой строки . Чтобы исправить это, измените кишки функции на

  if read -rx then { printf "%s\n" "$x"; cat; } > "$1" elif [ "$x" != "" ] then printf "%s" "$x" > "$1" fi 

Я использовал printf вместо echo для защиты от текста, начинающегося с тире или содержащего обратную косую черту. Могут возникнуть проблемы, если первая строка вывода stderr содержит символы, отличные от ASCII.