web-dev-qa-db-fra.com

Rediriger STDERR/STDOUT d'un processus APRÈS son démarrage, en ligne de commande?

Dans le shell, vous pouvez effectuer une redirection, ><, etc., mais qu'en est-il après le démarrage d'un programme?

Voici comment je suis arrivé à poser cette question: un programme exécuté en arrière-plan de mon terminal continue de générer des textes gênants. C'est un processus important, je dois donc ouvrir un autre shell pour éviter le texte. J'aimerais pouvoir utiliser >/dev/null ou une autre redirection pour pouvoir continuer à travailler dans le même shell.

108
Ian Kelling

À moins de fermer et de rouvrir votre terminal (c'est-à-dire vous déconnecter et vous reconnecter, ce qui peut également mettre fin à certains de vos processus d'arrière-plan au cours du processus), il ne vous reste qu'un choix:

  • attachez-vous au processus en question à l’aide de gdb et exécutez:
    • p dup2 (open ("/ dev/null", 0), 1)
    • p dup2 (open ("/ dev/null", 0), 2) 
    • détacher
    • quitter

par exemple.:

$ 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

Vous pouvez également considérer:

  • en utilisant screen; L’écran fournit plusieurs TTY virtuels que vous pouvez basculer sans avoir à ouvrir de nouvelles sessions SSH/telnet/etc.
  • en utilisant Nohup; Cela vous permet de fermer et de rouvrir votre session sans perdre aucun processus d'arrière-plan dans le processus ....
110
vladr

Cela fera:

strace -ewrite -p $PID

Ce n'est pas si propre (affiche des lignes comme: write(#,<text you want to see>)), mais ça marche!


Vous pourriez également ne pas aimer le fait que les arguments soient abrégés. Pour contrôler cela, utilisez le paramètre -s qui définit la longueur maximale des chaînes affichées.

Il intercepte tous les flux, vous pouvez donc filtrer cela en quelque sorte:

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

affiche uniquement les appels du descripteur 1. 2>&1 consiste à rediriger STDERR vers STDOUT, car strace écrit sur STDERR par défaut.

55
naugtur

résumant l'excellente recherche de vladr (et d'autres):

créez les deux fichiers suivants dans le même répertoire, quelque chose dans votre chemin, par exemple $ HOME/bin:

silence.gdb, contenant (d'après la réponse de vladr):


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

et silence, contenant:


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

Par exemple, la prochaine fois que vous oubliez de rediriger firefox, votre terminal commence à être encombré par l’inévitable "(firefox-bin: 5117): message Gdk-WARNING **: XID collision, trouble ahead":


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

Vous pouvez également rediriger la sortie de gdb vers/dev/null si vous ne voulez pas la voir.

18
jcomeau_ictx

Redirige la sortie d'un processus en cours d'exécution vers un autre terminal, fichier ou écran:

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

À l'intérieur gdb :

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

Détachez un processus en cours d'exécution de bash terminal et maintenez-le actif:

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

Explication:

20818 - juste un exemple de processus en cours d'exécution pid
p - résultat d'impression de la commande gdb
close (1) - sortie standard proche
/dev/pts/4 - terminal sur lequel écrire
close (2) - sortie d'erreur close
/tmp/myerrlog - fichier dans lequel écrire
q - quitter Gdb
bg% 1 - exécution du travail 1 arrêté en arrière-plan
disown% 1 - détache le travail 1 du terminal

14
Mirek

Ce n’est pas une réponse directe à votre question, mais c’est une technique que j’ai trouvée utile ces derniers jours: exécutez la commande initiale en utilisant "screen", puis détachez.

3
Roger Lipscombe

ceci est une partie de script bash basée sur les réponses précédentes, qui redirige le fichier journal lors de l'exécution d'un processus ouvert, il est utilisé comme postscript danslogrotateprocess

#!/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
2
Mostafa Nazari

Vous pouvez utiliser reredirect ( https://github.com/jerome-pouiller/reredirect/ ).

Type

reredirect -m FILE PID

et les sorties (standard et erreur) seront écrites dans FILE.

reredirect README explique également comment restaurer l'état initial du processus, rediriger vers une autre commande ou rediriger uniquement stdout ou stderr.

reredirect fournit également un script appelé relink qui permet de rediriger vers le terminal actuel:

relink PID
relink PID | grep usefull_content

(reredirect semble avoir les mêmes fonctionnalités que Dupx décrit dans une autre réponse mais cela ne dépend pas de Gdb).

0
Jezz

Dupx est un utilitaire simple * nix permettant de rediriger la sortie/entrée/erreur standard d’un processus en cours.

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

0
eMPee584