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.
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èmeclose()
et passe le descripteur de fichier 1, puis un appel systèmecreat()
à ouvrir un nouveau fichier. Le résultat decreat()
é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èmedup2()
pour obtenir ce résultat.Pour cet exemple, j'ai choisi d'utiliser
creat()
au lieu deopen()
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()
.
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).
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).
é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.
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.