web-dev-qa-db-fra.com

Comment rediriger la sortie d'un processus en cours d'exécution

Normalement, je lancerais une commande comme 

longcommand &;

Je sais que vous pouvez le rediriger en faisant quelque chose comme

longcommand > /dev/null;

par exemple pour se débarrasser de la sortie ou

longcommand 2>&1 > output.log

capturer la sortie.

Mais parfois, j'oublie et je me demandais s'il y avait un moyen de capturer ou de rediriger après coup.

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

ou quelque chose comme ça pour que je puisse continuer à utiliser le terminal sans que des messages n'apparaissent sur le terminal.

121
Sheldon Ross

Voir Redirection de la sortie d'un processus en cours d'exécution.

Premièrement, j'exécute la commande cat > foo1 au cours d'une session et teste le fait que les données de stdin sont copiées dans le fichier. Puis, dans une autre session, je redirige la sortie.

Tout d'abord trouver le PID du processus:

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

Maintenant, vérifiez que le fichier gère est ouvert:

$ 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

Maintenant, lancez 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

La commande p dans GDB affichera la valeur d'une expression, une expression pouvant être une fonction à appeler, un appel système… Je lance donc un appel système close() et passe le descripteur de fichier 1, puis un appel système creat() à ouvrir un nouveau fichier. Le résultat de creat() était 1, ce qui signifie qu'il a remplacé le descripteur de fichier précédent. Si je voulais utiliser le même fichier pour stdout et stderr ou si je voulais remplacer un descripteur de fichier par un autre numéro, il me faudrait appeler l'appel système dup2() pour obtenir ce résultat.

Pour cet exemple, j'ai choisi d'utiliser creat() au lieu de open() car il y a moins de paramètre. Les macros C pour les drapeaux ne sont pas utilisables dans GDB (il n’utilise pas d’en-têtes C). Je devrais donc lire les fichiers d’en-tête pour le découvrir. Ce n’est pas si difficile, mais cela prendrait plus de temps. Notez que 0600 est l'autorisation octale pour le propriétaire ayant un accès en lecture/écriture et le groupe et les autres personnes n'ayant pas d'accès. Il serait également utile d’utiliser 0 pour ce paramètre et d’exécuter chmod sur le fichier ultérieurement.

Après cela, je vérifie le résultat:

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

Si vous saisissez plus de données dans cat, le fichier /tmp/foo3 sera ajouté à.

Si vous souhaitez fermer la session d'origine, vous devez fermer tous les descripteurs de fichier correspondants, ouvrir un nouveau périphérique pouvant être le terminal de contrôle, puis appeler setsid().

111
user37875

Vous pouvez également le faire en utilisant 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 semble avoir les mêmes fonctionnalités que Dupx décrit dans une autre réponse mais cela ne dépend pas de Gdb).

15
Jezz

Dupx

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

Motivation

Je me suis souvent trouvé dans une situation où un processus démarré sur un système distant via SSH prend beaucoup plus de temps que prévu. Je dois rompre la connexion SSH, mais si je le fais, le processus mourra s'il essaie d'écrire quelque chose sur stdout/error d'un tuyau cassé. J'aimerais pouvoir suspendre le processus avec ^ Z puis faire une

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

Malheureusement, cela ne fonctionnera pas (dans les coquilles que je connais).

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

13
blah

écran

Si le processus est en cours d'exécution dans une session screen, vous pouvez utiliser la commande log de screen pour consigner la sortie de cette fenêtre dans un fichier:

Basculer vers la fenêtre du script, C-aH se connecter.
Maintenant vous pouvez :

$ tail -f screenlog.2 | grep whatever

De la page de manuel de l'écran:

log [on | off]

Commencez/arrêtez l'écriture de la sortie de la fenêtre en cours dans un fichier "screenlog.n" dans le répertoire par défaut de la fenêtre, où n est le numéro de la fenêtre en cours. Ce nom de fichier peut être changé avec la commande 'logfile'. Si aucun paramètre n'est fourni, l'état de la journalisation est basculé. Le journal de session est ajouté au contenu précédent du fichier s'il existe déjà. Le contenu actuel et le contenu de l'historique de défilement ne sont pas inclus dans le journal de session. La valeur par défaut est "off".

Je suis sûr que tmux a aussi quelque chose de similaire.

7
lemonsqueeze

J'ai collecté des informations sur Internet et préparé un script qui ne nécessite aucun outil externe: Voir ma réponse ici . J'espère que c'est utile.

0
Krzysztow