запишите stderr и stdout в файл без сценария-оболочки

#linux #bash #shell #pipe #file-descriptor

Вопрос:

Я хочу перенаправить stderr и stdout в файл внутри моего сценария bash myscript.sh где выполняются некоторые подпроцессы. Самый простой способ-написать сценарий-оболочку start_myscript.sh это вызывает myscript.sh 2>amp;1 > logfile или myscript.sh amp;> logfile .

Интересно, можно ли перенаправить как stderr, так и stdout внутрь myscript.sh в файл журнала без использования сценария-оболочки? Для этого я открыл новый файловый дескриптор 3 и перенаправил stderr и stdout в fd3, который я перенаправляю в /tmp/файл журнала.

 #!/bin/bash
exec 3> /tmp/logfile
exec 1>amp;3
exec 2>amp;3
doing_something amp;
doing_other_things amp;
 

Обе функции что-то делают и выводят данные в stderr или stdout. Дело в том, что они работают одновременно и иногда одновременно пишут в stdout/stderr.
В этом случае предложение из первой функции прерывается, затем следует вывод из второй и, наконец, следует за последней частью предложения из первой функции. Это нарушает любой файл журнала…

Поэтому я подумал о поименованных каналах FIFO, как это должно быть, и провел короткий тест:

 #!/bin/bash

PIPE=/tmp/mypipe
mkfifo $PIPE

cat LONGTEXTFILE > $PIPE amp;
ls -la /usr/bin > $PIPE amp;
ls -la /tmp > $PIPE amp;
 

Тест очень прост. Я создаю именованный канал $PIPE, отправляю длинный текстовый файл в течение нескольких секунд в stdout, который перенаправляется в именованный канал. Я делаю это в фоновом режиме, пока короткие вызовы ls перенаправляют его вывод в именованный канал. Это должно имитировать вывод различных функций, одновременно работающих в фоновом режиме.

В другом терминале я открыл именованный канал с cat /tmp/mypipe

Мое предположение состояло в том, что именованный канал FIFO заблокирован, пока он получает входные данные cat , и вывод из ls него будет ждать, пока вывод из cat не закончится.

К сожалению, результат разочаровывает. Вывод из ls помещается где-то в середине вывода cat , а не после. Я совершил какие-нибудь ошибки?

Существует ли какой-либо другой способ перенаправления stderr/stdout из сценария в файл журнала без использования сценария-оболочки?

Комментарии:

1. exec правильно используется в вашем примере кода… Но stdout и stderr являются потоками, и если вы перенаправите их в один и тот же поток и выполните несколько одновременных операций записи, результаты этих разных операций записи будут перемешаны. Это присуще потокам.

2. Вы, наверное, путаете 2>amp;1 > logfile с > logfile 2>amp;1 .

3. @Сайрус, ты прав! Так и должно быть myscript.sh > logfile 2>amp;1 . Хорошее объяснение я нашел в mywiki. wooledge.org/BashFAQ/055 @Jean-LoupSabatier Да, я думаю, что застрял здесь, и нет другого решения, кроме как использовать сценарий-оболочку? Верно? Но чем отличаются сценарии-оболочки, которые собирают одновременные потоки из потоков правильно и не смешиваются?