2009-02-27 19 views
101

En el shell puede hacer una redirección, ><, etc., pero ¿qué ocurre DESPUÉS de iniciar un programa?¿Redirigir STDERR/STDOUT de un proceso DESPUÉS de que se haya iniciado, usando la línea de comando?

Así es como llegué a hacer esta pregunta, un programa que se ejecuta en el fondo de mi terminal sigue emitiendo texto molesto. Es un proceso importante, así que tengo que abrir otro caparazón para evitar el texto. Me gustaría poder >/dev/null o alguna otra redirección así puedo seguir trabajando en el mismo shell.

+0

sé la manera más fácil para redirigir la salida estándar/stderres a dup2 sus descriptores de archivos antes de que se bifurcan. Esta es una práctica bastante estándar, y probablemente la forma en que las conchas lo logran en este momento.No estoy seguro si eso da una respuesta, pero estoy pensando que disminuye las posibilidades de que haya una buena. –

+1

[reptyr] (https://github.com/nelhage/reptyr) – Louis

Respuesta

104

corto de cierre y reapertura de su TTY (es decir, cerrar la sesión y volver a encender, que también puede terminar algunas de sus procesos de fondo en el proceso) sólo tiene una opción que queda:

  • asociar al proceso de pregunta usando gdb, y ejecute:
    • dup2 p (abierta ("/ dev/null", 0), 1)
    • dup2 p (abierta ("/ dev/null", 0), 2)
    • detach
    • dejar de fumar

ej .:

$ 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 

También puede considerar:

  • usando screen; la pantalla proporciona varios TTY virtuales que puede cambiar sin tener que abrir nuevas sesiones SSH/telnet/etc, sesiones
  • usando nohup; esto le permite cerrar y volver a abrir su sesión sin perder ningún proceso en segundo plano en el ... proceso.
+1

Su respuesta gdb no funcionó con el archivo tail -f, y no funcionó con un programa de prueba en c compilado con gcc -ggdb que hace una impresión cada segundo. Además, cont no permite ejecutar más comandos gdb, el comando se separaría y luego se cerraría. –

+0

Correcto sobre despegar, son las 2AM. :) ¿Qué exactamente no funcionó con la solución gdb? – vladr

+0

Malo, no solo he tenido un error de cont/detach, sino que mi dup2 fue intercambiado. Debería funcionar ahora. – vladr

3

No es una respuesta directa a su pregunta, pero es una técnica que he encontrado útil en los últimos días: ejecute el comando inicial usando 'pantalla', y luego separe.

53

Esto va a hacer:

strace -ewrite -p $PID 

No es que limpia (como muestra líneas: write(#,<text you want to see>)), pero funciona!


También le puede molestar el hecho de que los argumentos estén abreviados. Para controlar eso, use el parámetro -s que establece la longitud máxima de las cadenas que se muestran.

atrapa todas las corrientes, así que sería bueno para filtrar que de alguna manera:

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

muestra solamente descriptor 1 llama. 2>&1 es redirigir STDERR a STDOUT, ya que strace escribe a STDERR de manera predeterminada.

+0

Esta es una gran solución. –

+6

Esto no es lo que solicitó OP. OP pidió REDIRECTAR lejos del TTY, no interceptarlo. Además, en algunas plataformas, strace/truss insertará espacios entre los caracteres de la secuencia interceptada y/o escapará de los que no sean ASCII, y usted tendrá que lidiar con el procesamiento de esos también. – vladr

+3

Sí, esto lo hace parcialmente, pero para algunas personas que leen esta pregunta es todo lo que necesitan: para ver lo que está sucediendo en un programa ejecutado erróneamente para escribir en nulo o en otra consola. Lo descubrí después de encontrar esta pregunta en el proceso y pensé que era un buen truco (al menos para mí). Y bastantes personas encuentran útil si mis ojos no me engañan;) – naugtur

14

Redirigir la salida de un proceso en ejecución a otro terminal, archivo o pantalla:

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

Dentro GDB:

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

Separar un proceso en ejecución de fiesta terminal y mantenerlo vivo :

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

Explicación:

20818 - sólo un ejemplo de funcionamiento del proceso PID
p - resultado de la impresión de mando GDB
cierre (1) - cerca de la salida estándar
/dev/pts/4 - terminal de escribir en
cierre (2) - cerca de la salida de error
/tmp myerrlog/- archivo para escribir en
q - dejar de fumar gDB
bg% 1 - run parado de trabajo 1 en el fondo
disown% 1 - separar el trabajo 1 de la terminal

+1

Esto no funcionará si 'stdin' (descriptor de archivo' 0') está cerrado. – pabouk

+0

Esto me salvó el día. Tuve una marca en ejecución en una sesión de SSL que tardó una hora en el primer 10% y realmente no quería que mi computadora portátil siguiera funcionando durante otras 10 horas. Pero estoy en lo cierto al suponer que su redirección para stderr debería leer 'p open ("/tmp/myerrlog ", 2)' ? –

+0

Tuve un problema menor con este funcionamiento en CentOS 6: el archivo "/ tmp/myerrlog" tenía que existir ya. Era trivial crearlo con tacto, por supuesto. – ebneter

18

riffs fuera de vladr (y de otros) una investigación de excelencia:

crear los siguientes dos archivos en el mismo directorio, algo en su camino, por ejemplo, $ HOME/bin:

silence.gdb, que contiene (de la respuesta de vladr):


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

y silencio, que contiene:


#!/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 

Ahora, la próxima vez que olvide redirigir a Firefox, por ejemplo, y su terminal empiece a saturarse con el inevitable mensaje "(firefox-bin: 5117): Gdk-WARNING **: colisión XID, problemas futuros":


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 

también puede redirigir la salida del BGF a/dev/null si no quieres verlo.

+1

Mi gdb (v7.2) tiene una práctica opción '--batch-silent' que suprime el resultado y no lo lanza a la consola gdb si algo sale mal (por ejemplo, falta un proceso). Por cierto, '$!' Se refiere al trabajo en segundo plano más reciente, pero no creo que pueda usarse en el script en sí. Yo uso un alias: 'alias silencebg = 'silence $!'' – seanf

2

esto es parte escritura del golpe sobre la base de las respuestas anteriores, que redirigen el archivo de registro durante la ejecución de un proceso abierto, se utiliza como PostScript en logrotate proceso

#!/bin/bash 

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

reloadLog() 
{ 
    getStatus 
    if [ "$pid" = "" ]; then 
     showStatus 
    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 
Cuestiones relacionadas