Перенаправить STDERR / STDOUT процесса ПОСЛЕ его запуска, используя командную строку? - PullRequest
112 голосов
/ 27 февраля 2009

В оболочке вы можете сделать перенаправление, > < и т. Д., Но как насчет ПОСЛЕ запуска программы?

Вот как я пришел, чтобы задать этот вопрос: программа, работающая в фоновом режиме моего терминала, продолжает выводить раздражающий текст. Это важный процесс, поэтому мне нужно открыть другую оболочку, чтобы избежать текста. Я хотел бы иметь возможность >/dev/null или какое-либо другое перенаправление, чтобы я мог продолжать работать в той же оболочке.

Ответы [ 8 ]

111 голосов
/ 27 февраля 2009

За исключением закрытия и повторного открытия вашего tty (то есть выхода из системы и повторного включения, что также может завершить некоторые ваши фоновые процессы в процессе), у вас остается только один выбор:

  • присоединитесь к рассматриваемому процессу, используя gdb, и запустите:
    • p dup2 (open ("/ dev / null", 0), 1)
    • p dup2 (open ("/ dev / null", 0), 2)
    • открепление
    • 1012 * бросить курить *

например:.

$ tail -f /var/log/lastlog &
[1] 5636

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/pts/0
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog

$ gdb -p 5636
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Attaching to process 5636
Reading symbols from /usr/bin/tail...(no debugging symbols found)...done.
Reading symbols from /lib/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/librt.so.1
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
[New Thread 0x7f3c8f5a66e0 (LWP 5636)]
Loaded symbols for /lib/libpthread.so.0
Reading symbols from /lib/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2

(no debugging symbols found)
0x00007f3c8eec7b50 in nanosleep () from /lib/libc.so.6

(gdb) p dup2(open("/dev/null",0),1)
[Switching to Thread 0x7f3c8f5a66e0 (LWP 5636)]
$1 = 1

(gdb) p dup2(open("/dev/null",0),2)
$2 = 2

(gdb) detach
Detaching from program: /usr/bin/tail, process 5636

(gdb) quit

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/null
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog
lr-x------ 1 myuser myuser 64 Feb 27 07:36 4 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 5 -> /dev/null

Вы также можете рассмотреть:

  • с использованием screen; screen предоставляет несколько виртуальных TTY, между которыми вы можете переключаться без необходимости открывать новый SSH / telnet / etc, сессий
  • с использованием nohup; это позволяет вам закрыть и снова открыть сеанс, не теряя никаких фоновых процессов в ... process.
56 голосов
/ 14 сентября 2009

Это будет делать:

strace -ewrite -p $PID

Это не так чисто (показывает строки вроде: write(#,<text you want to see>)), но работает!


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

Он перехватывает все потоки, так что вы можете захотеть отфильтровать это так:

strace -ewrite -p $PID 2>&1 | grep "write(1" 

показывает только вызовы дескриптора 1. 2>&1 предназначен для перенаправления STDERR в STDOUT, так как strace записывает в STDERR по умолчанию.

18 голосов
/ 01 ноября 2010

отрывистое исследование Владра (и других):

создайте следующие два файла в одном каталоге, что-то на вашем пути, скажем $ HOME / bin:

silence.gdb, содержащий (из ответа vladr):


p dup2(open("/dev/null",0),1)
p dup2(open("/dev/null",0),2)
detach
quit

и тишина, содержащие:


#!/bin/sh
if [ "$0" -a "$1" ]; then
 gdb -p $1 -x $0.gdb
else
 echo Must specify PID of process to silence >&2
fi

chmod +x ~/bin/silence  # make the script executable

Теперь, в следующий раз, когда вы забудете, например, перенаправить firefox, и ваш терминал начнет загромождаться неизбежными сообщениями "(firefox-bin: 5117): Gdk-WARNING **: коллизия XID, проблемы впереди":


ps  # look for process xulrunner-stub (in this case we saw the PID in the error above)
silence 5117  # run the script, using PID we found

Вы также можете перенаправить вывод GDB в / dev / null, если вы не хотите его видеть.

15 голосов
/ 01 октября 2010

Перенаправить вывод из запущенного процесса в другой терминал, файл или экран:

tty
ls -l /proc/20818/fd
gdb -p 20818

Внутри GDB :

p close(1)
p open("/dev/pts/4", 1)
p close(2)
p open("/tmp/myerrlog", 1)
q

Отключение запущенного процесса от терминала bash и поддержка его:

[Ctrl+z]
bg %1 && disown %1
[Ctrl+d]

Пояснение:

20818 - просто пример запуска процесса pid
p - вывод результата команды gdb
close (1) - закрыть стандартный вывод
/ dev / pts / 4 - терминал для записи в
close (2) - вывод ошибки закрытия
/ tmp / myerrlog - файл для записи в
q - выйти из GDB
bg% 1 - запустить остановленное задание 1 в фоновом режиме
disown% 1 - отсоединить задание 1 от терминала

3 голосов
/ 27 февраля 2009

Не прямой ответ на ваш вопрос, но это метод, который я нашел полезным в течение последних нескольких дней: выполните начальную команду, используя 'screen', а затем отсоедините.

2 голосов
/ 19 февраля 2014

это часть скрипта bash, основанная на предыдущих ответах, которая перенаправляет файл журнала во время выполнения открытого процесса, она используется как postscript в logrotate process

#!/bin/bash

pid=$(cat /var/run/app/app.pid)
logFile="/var/log/app.log"

reloadLog()
{
    if [ "$pid" = "" ]; then
        echo "invalid PID"
    else
        gdb -p $pid >/dev/null 2>&1 <<LOADLOG
p close(1)
p open("$logFile", 1)
p close(2)
p open("$logFile", 1)
q
LOADLOG
        LOG_FILE=$(ls /proc/${pid}/fd -l | fgrep " 1 -> " | awk '{print $11}')
        echo "log file set to $LOG_FILE"
    fi
}

reloadLog
1 голос
/ 29 ноября 2017

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

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

0 голосов
/ 11 июня 2019

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

Тип

reredirect -m FILE PID

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

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

reredirect также предоставляет скрипт под названием relink, который позволяет перенаправить на текущий терминал:

relink PID
relink PID | grep usefull_content

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...