web-dev-qa-db-fra.com

Comment afficher la sortie d'un processus en cours dans une autre session bash?

J'ai laissé un script en cours d'exécution sur une machine distante à partir du moment où j'y travaillais localement. Je peux me connecter via SSH à la machine en tant que même utilisateur et voir le script s'exécuter dans ps.

$ ps aux | grep ipcheck
myuser  18386  0.0  0.0  18460  3476 pts/0    S+   Dec14   1:11 /bin/bash ./ipchecker.sh

Il est simplement sorti sur stdout sur une session locale (j'ai exécuté ./ipchecker.sh forme une fenêtre de terminal local, pas de redirection, pas d'utilisation de screen etc).

Existe-t-il de toute façon à partir d'une session SSH que je peux voir la sortie de cette commande en cours d'exécution (sans l'arrêter)?

Jusqu'à présent, le meilleur que j'ai trouvé est d'utiliser strace -p 18386 mais je reçois des hordes de texte qui montent sur l'écran, c'est beaucoup trop détaillé. Je peux arrêter strace puis passer en revue la sortie et trouver le texte à imprimer sur stdout mais c'est très long et déroutant, et évidemment pendant qu'il est arrêté, je risque de manquer quelque chose. Je voudrais trouver un moyen de voir la sortie du script en direct comme si je travaillais localement.

Quelqu'un peut-il améliorer cela? La réponse évidente est de redémarrer le script avec redirection ou dans une session screen etc, ce n'est pas un script critique pour la mission, donc je pourrais le faire. Au contraire, je vois cela comme un exercice d'apprentissage amusant.

223
jwbensley

Si tout ce que vous voulez faire, c'est espionner le processus existant, vous pouvez utiliser strace -p1234 -s9999 -e write où 1234 est l'ID du processus. (-s9999 évite d'avoir des chaînes tronquées à 32 caractères et write l'appel système qui produit la sortie.) Si vous souhaitez afficher uniquement les données écrites sur un descripteur de fichier particulier, vous pouvez utiliser quelque chose comme strace -p1234 -e trace= -e write=3 pour afficher uniquement les données écrites dans le descripteur de fichier 3 (-e trace= empêche les appels système d'être enregistrés). Cela ne vous donnera pas de sortie déjà produite.

Si la sortie défile trop rapidement, vous pouvez la diriger vers un pager tel que less, ou l'envoyer vers un fichier avec strace -o trace.log ….

Avec de nombreux programmes, vous pouvez détourner la sortie suivante avec un hack ptrace, soit vers votre terminal actuel, soit vers une nouvelle session d'écran. Voir Comment puis-je désavouer un processus en cours et l'associer à un nouveau shell d'écran? et autres threads liés.

Notez que selon la configuration de votre système, vous devrez peut-être exécuter toutes ces commandes strace en tant que root même si le processus s'exécute sous votre utilisateur sans privilèges supplémentaires. (Si le processus s'exécute en tant qu'utilisateur différent ou est setuid ou setgid, vous devrez exécuter strace en tant que root.) La plupart des distributions permettent uniquement à un processus de tracer ses enfants (ce fournit un avantage de sécurité modéré - il empêche certaines injections directes de logiciels malveillants, mais n'empêche pas l'injection indirecte en modifiant les fichiers). Ceci est contrôlé par le kernel.yama.ptrace_scome sysctl.

Vous pouvez accéder à la sortie via le système de fichiers proc.

tail -f /proc/<pid>/fd/1

1 = stdout, 2 = stderr

164
tvlooy

Dans BSD, vous pouvez utiliser watch qui espionne un tty donné, par exemple.

watch /dev/pts/0

Sous Linux, ce ne sera pas possible si le processus n'a pas été exécuté sous multiplexeur auparavant comme screen ou tmux. Voir aussi: Reptyr: attacher un processus en cours d'exécution à un nouveau terminal

Il semble que le seul moyen soit de déboguer le processus (par exemple strace, dtrace/dtruss, gdb , lldb, etc.).

Puisque vous avez utilisé strace, pour récupérer une sortie significative, vous devez filtrer par une expression de qualification (telle que file), puis analyser la sortie. Voici un exemple:

strace -e trace=write -s1000 -fp 18386 2>&1 | grep -o '".\+[^"]"'

Ce qu'il fait, il imprime l'opération d'écriture du processus (longueur 1000) spécifié par PID (utilisez pgrep pour le trouver par son nom), redirige l'erreur standard vers la sortie (à filtrer) et imprime une chaîne entre guillemets.

Si vous avez affaire à une sortie binaire, vous pouvez analyser les caractères des séquences d'échappement en utilisant read (avec -r) et printf (avec %b), par exemple.

while read -r -t1 line; do printf "%b" $line; done

Vérifier help read pour plus de paramètres (par exemple -n pour imprimer après un certain nombre de caractères, plutôt que la nouvelle ligne).

Voici un exemple plus complet:

strace -e trace=write -s1000 -fp 18386 2>&1 \
| grep --line-buffered -o '".\+[^"]"' \
| grep --line-buffered -o '[^"]\+[^"]' \
| while read -r line; do
  printf "%b" $line;
done

Pour des exemples utilisant n'importe quel processus, veuillez vérifier: Comment analyser strace dans Shell en texte brut? at stackoverflow

10
kenorb

Je vous conseille de créer un canal nommé (mkfifo), puis d'écrire dans ce fichier. Ensuite, lisez-le. Vous pouvez toujours le faire avec des choses comme tail, pour minimiser la sortie, etc. Chaque fois que vous effacez le canal (lu à partir de celui-ci), il est effacé, donc la sortie n'est pas conservée.

L'autre option serait de tout écrire dans un fichier (un peu comme un fichier journal) puis de l'analyser à tout moment. Ce serait l'action préférée, si vous souhaitez conserver toutes les sorties.

4
polemon
  1. Vous pourrez peut-être jeter un œil à l'écran distant à l'aide de ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scalelocalhost doit être remplacé par vos identifiants de connexion au serveur distant et :0.0 avec le numéro d'affichage de votre interface graphique.

  2. Utilisation x11vnc, qui est un serveur VNC pour votre session X à l'écran.

  3. Lors de l'exécution sur l'une des 6 consoles virtuelles, essayez Sudo setterm -dump 2 -file /dev/stdout, où vous remplacez 2 avec le vc approprié.

4
jippie

Vous pouvez toujours lancer un processus avec Nohup et &

Nohup rsync source_file dest_file &

Ensuite, vous pourrez vérifier la progression de n'importe quel terminal avec:

tail -f Nohup.out

Cela fonctionne bien pour moi.

3
Pablo Luna

Analyse de la sortie de strace:

J'ai utilisé le réponse du haut (avec mon ID de processus de 28223) ...

> Sudo strace -p28223 -s9999 -e write
...
write(9, "Info\nI\nCare\nabout", 55) = 55
...

Pour déterminer que je me soucie de write(9. (Le 9 est utilisé ci-dessous, c'est probablement un descripteur de fichier et peut être différent pour votre processus.) Ensuite, j'ai écrit un rapide script Ruby pour les analyser et les afficher.

Collez ce qui suit dans /usr/bin/parse_strace.rb

#!/usr/bin/Ruby

num = ARGV[0]
STDIN.each { |line|
  if (line.match(/write\(#{ num },\s*"(.*?)"/)) then
    puts $1.split('\x').map { |s| s.to_i(16).chr }.join()
  end
}

N'oubliez pas chmod a+x /usr/bin/parse_strace.rb

J'invoque strace -xx (sort hex, donc le regex correspond correctement), tuyauterie (y compris STDERR) à mon script avec 9 comme premier argument.

Sudo sh -c 'strace -xx -p28223 -s9999 -e write 2>&1 | parse_strace.rb 9'

Et, le tour est joué, il sort le STDOUT original, les nouvelles lignes, la couleur et tout!

Attaching to process STDOUT

3
Jeff Ward

Une méthode très simple pour obtenir la sortie serait de capturer votre sortie dans un fichier et de suivre ce fichier.

SI FAIRE: ./ipcheck

AU LIEU FAIRE: ./ipcheck> [remplacez par votre nom de fichier]

Cela créerait un fichier de sortie où se trouve votre script. Ensuite, à partir de tout autre shell bash, vous pouvez simplement suivre le fichier:

queue [remplacez par votre nom de fichier] -f

1
MrAllen

ne pouvez-vous pas obtenir l'ID de processus et communiquer avec lui avec USR1,

$pgrep -l '^ipchecker.sh$'

qui imprime le PID de votre script, puis utilisez-le pour

$ kill -USR1 PID

Je comprends que USR1 est un signal "défini par l'utilisateur", ce qui signifie que celui qui a créé le programme peut l'utiliser pour signifier "arrêter" ou "vider vos journaux" ou "imprimer foo mille fois" ou autre.

0
Saeed