Как правильно запустить программу и сделать возможным перенаправление ее текущего вывода (stdout и stderr) на более позднем этапе?

Как правильно запустить программу и сделать возможным перенаправление ее текущего вывода (stdout и stderr) на более позднем этапе?

Проблема довольно проста: я считаю полезным иметь возможностьвключить (и выключить)вывод какой-то работающей программы в каждый момент, который мне нужен. Если быть точнее, я хочу иметь возможность свободно перенаправлять их стандартный вывод (и ошибку) из текущей оболочки в другую, в , /dev/nullв файл или обратно в исходную оболочку.

Я ищу что-то прямое (и безопасное), что использует тот факт, что я знаюзаранеечто я буду включать и выключать выходы. Я также публикую ответ.


Ниже моя первая попытка. Предположим, я работаю в корпусе номер 35.

$ who am I                     # the command line to ask where am I
myuser  pts/35  ...            # The answer 

Моя попытка начинается с символической ссылки на этот терминал

ln -s /dev/pts/35  MyOutput  # The command to link

Идея состоит в том, чтобы запустить программу с установленным перенаправлением на эту ссылку.

./Execute_program > MyOutput

Это работает, перенаправляет вывод на мой терминал, но когда я даю команду изменить ссылку,

ln -sf  /dev/null  MyOutput

ссылка меняется,но перенаправление не меняетсякак я и надеялся. Это не меняется для запущенного процесса. Если я запускаю новую программу таким же образом, перенаправление следует новому предписанию ссылки. Если я
запускаю снова и устанавливаю ссылку на /dev/nullвывод, он подавляется, как и ожидалось, но снова, когда я меняю ссылку, перенаправление не меняется.
Если я делаю ссылку на ссылку, я получаю тот же результат. Использование hard linkне меняет ситуацию.

Грустнооболочка расширяет командную строку во время запуска.

Есть ли возможность сделать эту работу аналогичным образом или мне нужно найти способ сообщить процессу (или PPID) об изменении ссылки?


Примечания:

Это вопрос из серии «Как перенаправить вывод запущенного процесса?», но он начинается не с того места«Опс, я запустил программу и забыл перенаправить вывод. Теперь я хочу это сделать», а с другой стороны: «Как я могу запустить программу с явной целью перенаправить вывод в другое место на более позднем этапе?».

Я намерен использовать такую ​​процедуру, когда невозможно (или неудобно) модифицировать исходный код программы.
Ячитатьчто можно disownобрабатывать, использовать screenи переносить с одного экрана на другой... или использовать отладчик, чтобы перехватить процесс... Все эти решения могли бы работать при наличии достаточного опыта и усилий, но некоторые из них также представляют определенный процент риска.

решение1

Я нахожу решение через mkfifo, которое создает именованный канал, илиFIFO.
Просто создайте символическую ссылку и сможете использовать все перенаправления, разрешенные в оболочке.

mkfifo MyOutput

ls -lдает

0 prw-r--r-- 1 My_username My_username  0 May 11 17:45 MyOut|

Я могу запустить программу с перенаправлением на эту ссылку

./Execute_program > MyOutput  &  cat MyOutput 

и вывод начинает поступать на терминал.

Если я нажимаю ctrl+, cя прерываю поток, но не запущенный процесс (мне нужно использовать что-то вроде kill pidили , kill %1чтобы сделать это).
Когда во второй раз я спрошуFIFOдля сброса на терминал (снова с помощью cat MyOutput) он начнет выводить вывод с этого момента.

Примечания и предупреждения:

  • Пока я не попрошу дамп из FIFOsнего будет держать весь вывод.
    Как я попрошу в первый раз, он будетвымыватьвсе.
  • Я могу перенаправить (или добавить) в другой файлcat MyOutput >> NewRealFile
  • Я могу использовать cat MyOutputи с другого терминала!
  • Предупреждение: Если я попрошу две разные программы (или экземпляры) перенаправить вывод в одну и ту же программу, FIFOsпоток будет объединен (нетаприориспособ отличить, из каких программ взята эта строка).
  • Предупреждение: Если я спрошу 2 или более раз (возможно, с разных терминалов), он выдаст одну строку для каждого запроса, разделив вывод для запрашивающего. Может быть, есть безопасный обходной путь...

решение2

Если я правильно понял ваш вопрос:

script 1>>~/out.fifo 2>>~/error.fifo 

то для мониторинга вы можете сделать что-то вроде:

watch cat ~/out.fifo

Вместо FIFO можно использовать настоящие файлы.

script 1>/tmp/$0-out 2>/tmp/$0-error

затем выполните команду tail -f, и они будут заменены при повторном запуске скриптов.

Я предпочитаю второй метод, или просто использование мультиплексора (т.е. экрана или какой-либо другой популярной реинкарнации на этой неделе)

screen -t "name" bash -c 'script'

затем

screen -r

для «мониторинга» и ctrl+ad для отключения.

Обязательно сделайте паузу в конце скрипта, если вы хотите увидеть результат его выполнения.

решение3

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

Связанный контент