183 votes

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

pour capturer la sortie.

Mais il m'arrive d'oublier, et je me demandais s'il existait 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 apparaissent dans le terminal.

2 votes

SO n'est probablement pas optimal pour ces questions. Je pense que le SU est le meilleur, bien que le SF puisse avoir une meilleure chance d'y répondre. Ma meilleure compréhension, BTW : essayez disown si cela échoue, vous n'avez pas de chance.

1 votes

Vous voulez probablement dire > où vous avez écrit |. Les deux côtés d'un pipe doivent être exécutables. Si vous redirigez vers un fichier ou un périphérique (tel que /dev/null), vous utilisez > et <.

164voto

user37875 Points 2474

Ver Rediriger la sortie d'un processus en cours .

Je lance d'abord la commande cat > foo1 dans une session et tester que les données de stdin sont copiées dans le fichier. Puis, dans une autre session, je redirige la sortie.

Tout d'abord, trouvez 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 les poignées de fichiers qu'il a ouvertes :

$ 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

El p dans GDB imprimera la valeur d'une expression, une expression peut être une fonction à appeler, un appel système J'exécute donc une commande close() appel système et passe le handle de fichier 1, puis j'exécute un creat() appel système pour ouvrir un nouveau fichier. Le résultat de l'appel creat() était 1, ce qui signifie qu'il a remplacé l'ancien gestionnaire de fichier. Si je voulais utiliser le même fichier pour stdout et stderr ou si je voulais remplacer un handle de fichier par un autre nombre, je devrais appeler la fonction dup2() pour obtenir ce résultat.

Pour cet exemple, j'ai choisi d'utiliser creat() au lieu de open() parce qu'il y a moins de paramètres. Les macros C pour les drapeaux ne sont pas utilisables depuis GDB (il n'utilise pas les en-têtes C) donc je devrais lire les fichiers d'en-tête pour découvrir cela - ce n'est pas si difficile à faire mais cela prendrait plus de temps. Notez que 0600 est la permission octale pour le propriétaire ayant un accès en lecture/écriture et le groupe et les autres n'ayant aucun accès. Il est également possible d'utiliser 0 pour ce paramètre et d'exécuter chmod sur le fichier plus tard.

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

Saisir plus de données dans cat résulte dans le fichier /tmp/foo3 étant annexé.

Si vous voulez fermer la session originale, vous devez fermer tous les gestionnaires de fichiers, ouvrir un nouveau périphérique qui peut être le tty de contrôle, et ensuite appeler setsid() .

31 votes

Il est toujours préférable de copier l'essentiel ici plutôt que de faire un lien.

6 votes

L'essentiel : s'attacher au processus en cours d'exécution en utilisant gdb puis faites 'p close(1)' et 'p creat("/tmp/foo3", 0600)' pour rediriger STDOUT, puis déconnectez gdb tout en laissant le programme en cours. Une astuce astucieuse !

7 votes

Si j'avais pu te donner un vote positif pour chaque fois que j'ai utilisé le lien de ton post, tu aurais été dans le top 100 au moins. Au fait, ne ressentez-vous pas l'envie de sortir de la ligue utilisateurXXX ?

29voto

Jezz Points 92

Vous pouvez également le faire en utilisant reredirect ( https://github.com/jerome-pouiller/reredirect/ ).

La commande suivante redirige les sorties (standard et erreur) du processus PID a FILE :

reredirect -m FILE PID

El README de reredirect explique également d'autres fonctionnalités intéressantes : comment restaurer l'état original du processus, comment rediriger vers une autre commande ou rediriger uniquement stdout ou stderr.

L'outil fournit également relink , un script permettant de rediriger les sorties vers le terminal courant :

relink PID
relink PID | grep usefull_content

( reredirect semble avoir les mêmes caractéristiques que Dupx décrit dans une autre réponse mais, il ne dépend pas de Gdb).

16voto

blah Points 81

Dupx

Dupx est un utilitaire *nix simple pour rediriger la sortie standard/entrée/erreur d'un processus déjà en cours.

Motivation

Je me suis souvent retrouvé dans une situation où un processus que j'ai lancé 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 et ensuite faire un

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

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

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

0 votes

Le lien est interdit

12voto

lemonsqueeze Points 71

Écran

Si le processus est exécuté dans une session écran, vous pouvez utiliser la commande log de l'écran pour enregistrer la sortie de cette fenêtre dans un fichier :

Passez à la fenêtre du script, C-a H pour le journal.
Maintenant vous pouvez :

$ tail -f screenlog.2 | grep whatever

Extrait de la page de manuel de screen :

journal [on|off]

Démarre/arrête l'écriture de la sortie de la fenêtre courante 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 courante. Ce nom de fichier peut être modifié avec la commande 'logfile'. Si aucun paramètre n'est donné, 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.

1voto

Krzysztow Points 313

J'ai collecté quelques informations sur internet et préparé le script qui ne nécessite aucun outil externe : Voir ma réponse ici . J'espère que cela vous sera utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X