Как перенаправить вывод уже запущенного процесса

Обычно я запускаю команду вроде

longcommand &;

Я знаю, что вы можете перенаправить его, сделав что-то вроде

longcommand > /dev/null;

например, чтобы избавиться от вывода или

longcommand 2>&1 > output.log

захватить вывод.

Но я иногда забываю, и мне было интересно, есть ли способ перехватить или перенаправить после факта.

longcommand
ctrl-z
bg 2>&1 > /dev/null

или что-то в этом роде, чтобы я мог продолжать использовать терминал без сообщений, появляющихся на терминале.

5 ответов

Решение

См. Перенаправление вывода из запущенного процесса.

Сначала я запускаю команду cat > foo1 в одном сеансе и проверьте, что данные из stdin копируются в файл. Затем в другой сессии я перенаправляю вывод.

Сначала найдите PID процесса:

$ ps aux | grep cat
rjc 6760 0.0 0.0 1580 376 pts/5 S+ 15:31 0:00 cat

Теперь проверьте дескрипторы файлов, которые у него открыты:

$ ls -l /proc/6760/fd
total 3
lrwx—— 1 rjc rjc 64 Feb 27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 Feb 27 15:32 1 -> /tmp/foo1
lrwx—— 1 rjc rjc 64 Feb 27 15:32 2 -> /dev/pts/5

Теперь запустите GDB:

$ gdb -p 6760 /bin/cat
GNU gdb 6.4.90-debian

[license stuff snipped]

Attaching to program: /bin/cat, process 6760

[snip other stuff that's not interesting now]

(gdb) p close(1)
$1 = 0
(gdb) p creat("/tmp/foo3", 0600)
$2 = 1
(gdb) q
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: /bin/cat, process 6760

p Команда в GDB выведет значение выражения, выражение может быть функцией для вызова, это может быть системный вызов… Поэтому я выполняю close() системный вызов и передать дескриптор файла 1, затем я выполняю creat() системный вызов, чтобы открыть новый файл. Результат creat() был 1, что означает, что он заменил предыдущий дескриптор файла. Если бы я хотел использовать один и тот же файл для stdout и stderr или если бы я хотел заменить дескриптор файла каким-то другим номером, мне нужно было бы вызвать dup2() Системный вызов для достижения этого результата.

Для этого примера я решил использовать creat() вместо open() потому что есть меньше параметров. Макросы C для флагов не могут использоваться из GDB (он не использует заголовки C), поэтому я должен был бы прочитать файлы заголовков, чтобы обнаружить это - это не так сложно сделать, но это займет больше времени. Обратите внимание, что 0600 является восьмеричным разрешением для владельца, имеющего права на чтение / запись, а для группы и других лиц, не имеющих доступа. Также будет полезно использовать 0 для этого параметра и позже запустить chmod для файла.

После этого я проверяю результат:

ls -l /proc/6760/fd/
total 3
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 2008-02-27 15:32 1 -> /tmp/foo3 <====
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 2 -> /dev/pts/5

Введите больше данных в cat результаты в файле /tmp/foo3 быть добавленным к.

Если вы хотите закрыть исходный сеанс, вам нужно закрыть все файловые дескрипторы для него, открыть новое устройство, которое может быть управляющим tty, и затем вызвать setsid(),

Вы также можете сделать это с помощью переадресации ( https://github.com/jerome-pouiller/reredirect/).

Тип

reredirect -m FILE PID

и выходные данные (стандарт и ошибка) будут записаны в ФАЙЛ.

Переадресация README также объясняет, как восстановить исходное состояние процесса, как перенаправить на другую команду или перенаправить только stdout или stderr.

(Переадресация, похоже, обладает теми же возможностями, что и Dupx, описанный в другом ответе, но это не зависит от Gdb).

Dupx

Dupx - это простая *nix-утилита для перенаправления стандартного вывода / ввода / ошибки уже запущенного процесса.

мотивация

Я часто оказывался в ситуации, когда процесс, который я запустил в удаленной системе через SSH, занимает гораздо больше времени, чем я ожидал. Мне нужно разорвать соединение SSH, но если я это сделаю, процесс умрет, если попытается что-то записать в stdout / error сломанного канала. Я хотел бы приостановить процесс с ^Z, а затем сделать

bg %1 >/tmp/stdout 2>/tmp/stderr 

К сожалению, это не будет работать (в оболочках я знаю).

http://www.isi.edu/~yuri/dupx/

экран

Если процесс выполняется в сеансе экрана, вы можете использовать команду log экрана, чтобы записать вывод этого окна в файл:

Переключитесь в окно скрипта, Ca H для входа.
Теперь вы можете:

$ tail -f screenlog.2 | grep whatever

Из справочной страницы экрана:

войти [вкл | выкл]

Начать / остановить запись вывода текущего окна в файл "screenlog.n" в каталоге по умолчанию окна, где n - номер текущего окна. Это имя файла может быть изменено с помощью команды 'logfile'. Если параметр не указан, состояние ведения журнала переключается. Журнал сеанса добавляется к предыдущему содержимому файла, если он уже существует. Текущее содержимое и содержимое истории прокрутки не включены в журнал сеанса. По умолчанию выключено.

Я уверен, что у tmux есть что-то похожее.

Я собрал некоторую информацию в Интернете и подготовил сценарий, который не требует внешнего инструмента: см. Мой ответ здесь. Надеюсь, это полезно.

Другие вопросы по тегам