J'exécute un script depuis plusieurs jours maintenant. J'ai redirigé stdout vers $HOME/mylog
, mais je n'ai pas redirigé stderr car je pensais qu'il n'y aurait rien dessus. Soudain, des milliers de lignes ont commencé à sortir sur stderr, alors j'ai suspendu le travail. Existe-t-il un moyen de rediriger stderr vers $HOME/myerr
maintenant, sans avoir à redémarrer le script?
J'ai un accès sudo sur la box et c'est OS X.
Peut-être quelque chose utilisant le piégeage dtools?
Je ne peux pas perdre le travail que le script a fait jusqu'à présent et le redémarrer à partir de zéro. Existe-t-il un moyen de "vider les objets en mémoire" sur le disque, de geler le programme, de modifier les variables (par exemple les descripteurs de fichiers) et de reprendre avec le nouveau contexte?
la source
Réponses:
Je pense que c'est possible si vous attachez le processus de l'interpréteur associé à gdb. Je l'ai essayé avec ce perl one-liner
et cela fonctionne mais malheureusement pas avec un script bash similaire.
Tout d'abord, vous devez déterminer le PID de ce processus dont vous souhaitez capturer la sortie. Ensuite, démarrez
gdb
dans un autre terminal et exécutez les commandes gdb suivantesaprès cela, toutes les données écrites
stderr
sont redirigées vers/abs/olu/te/path/filename
, carattach PID
attache le processus à gdb et l'arrêtecall close(2)
ferme lestderr
filedescriptor du processus (carstdout
le filedescriptor est 1)call open(...)
ouvre un nouveau fichier et prend l'entier inutilisé le plus bas pour le descripteur de fichier nouvellement créé etdetach PID
continue le processusAu moins sur ma machine. Les deux premières lignes sont compatibles POSIX mais pas la troisième.
Le deuxième et le troisième argument de
open
la troisième ligne sont documentés dansman 2 open
. Dans mon cas, 65 signifie queopen
devrait créer le fichier et ouvrir le fichier en écriture seule, c'est-à-direO_WRONLY | O_CREAT
(défini dansfcntl.h
). Le troisième argument indique à open de créer le fichier avec une autorisation de lecture et d'écriture pour l'utilisateur, c'est-à-direS_IWUSR | S_IRUSR
(défini danssys/stat.h
). Vous devrez peut-être trouver par vous-même les valeurs appropriées sur votre machine.la source
C'est une réponse grossière et j'espère que quelqu'un d'autre fera mieux, mais si aucune autre idée n'apparaît, attachez gdb et forcez le processus à faire quelques appels système:
la source
open()
FD 1 s'empare? Ou vous n'avez qu'à appelerdup()
quelques fois?p open("errfile", O_WRONLY)
vraiment sur votre machine?p dup2(xxx, 2)
et ensuitep close(xxx)
oùxxx
est la valeur de retour duopen
. C'est une tâche délicate, mieux vaut ne pas utiliser ces commandes sur un processus de longue durée jusqu'à ce que vous soyez sûr qu'il n'y a pas d'autre choix./dev/null
comme monerrfile
donc je n'en ai pas eu besoinO_CREAT
. EtO_WRONLY
étant une macro, qu'elle se développe ou non dépend de si gdb a arrêté le processus sur une ligne où les symboles de débogage sont disponibles et la macro est définie. L'injection de code dans un processus avec gdb est dangereuse et personne ne devrait simplement copier ces commandes sans les comprendre.