Capture du stream de sortie de l’application .jar sur la console après la fermeture de la console et ouverture d’un nouveau sur Oracle Solaris 11

Sur la console Oracle Solaris 11 lorsque ps -ef | grep java ps -ef | grep java commande ps -ef | grep java est lancée. Je peux voir l’exécution d’un processus PID java qui a été démarré sur une autre fenêtre de la console, puis (la fenêtre de la console) a été fermée (la sortie de l’application .jar était alors visible). Est-il possible de récupérer cette sortie d’application sans redémarrer le fichier .jar?

L’application a été démarrée comme ceci (en tant qu’utilisateur root ):

 java -jar SomeFile.jar & 

Ecrire une sortie dans un fichier n’est pas une option dans ce cas.

Oui, vous pouvez le faire, mais cela implique des compétences folles avec gdb . Voici comment faire cela sous Linux et je pense que vous pouvez faire la même chose dans Solaris (car il a gdb et il a tous les appels système nécessaires que je vais utiliser plus loin).

Il existe 3 descripteurs de fichiers pour les stream standard:

  • stdin: 0
  • stdout: 1
  • stderr: 2

Vous êtes intéressé par stdout et stderr (les deux sont des sorties de console), vous avez donc besoin de descripteurs de fichiers avec les numéros 1 et 2 , gardez-les simplement à l’esprit.

Maintenant, je vais vous montrer comment faire ce que vous demandez pour une application “okular” (au lieu de votre application “java”) pour le stream stderr .

  1. Exécuter “okular” dans le terminal, comme ceci:

     $ okular & 

    puis fermez ce terminal. Ceci est juste pour simuler votre situation.

  2. Ouvrir un autre terminal
  3. Recherchez le processus “okular”:

     $ ps aux | grep okular 

    Sortie:

     joe 27599 2.2 0.9 515644 73944 ? S 23:46 0:00 okular 

    Donc PID “okular” est 27599 .

  4. Recherchez les descripteurs de fichiers ouverts du processus “okular”:

     $ ls -l /proc/27599/fd 

    Sortie:

     lrwx------ 1 joe joe 64 Feb 18 23:46 0 -> /dev/pts/0 (deleted) lrwx------ 1 joe joe 64 Feb 18 23:46 1 -> /dev/pts/0 (deleted) lrwx------ 1 joe joe 64 Feb 18 23:46 2 -> /dev/pts/0 (deleted) 

    Vous voyez que tous les 3 stream sont supprimés.

  5. Maintenant, attachons-nous à notre processus avec gdb :

     $ gdb -p 27599 /usr/bin/okular 

    À l’intérieur de gdb, effectuez les opérations suivantes:

     (gdb) p close(2) (gdb) p creat("/tmp/okular_2", 0600) (gdb) detach (gdb) quit 

    Ici, nous avons invoqué 2 appels système:

    • close () , pour fermer le fichier du stream stderr de notre processus
    • creat () , pour créer un nouveau fichier pour le stream stderr de notre processus

    p est la commande gdb, elle imprime (dans notre cas) les valeurs de retour des appels système.

  6. Toutes les nouvelles sorties de stderr de notre processus seront ajoutées au fichier texte / tmp / okular_2 . Nous pouvons le lire constamment de cette façon:

     $ tail -f /tmp/okular_2 

Conclusion

Ok, ça y est, nous avons relancé stderr stream. Vous pouvez faire la même chose pour le stream stdout , la seule différence est que vous devez appeler “close (1)” au lieu de “close (2)” dans gdb. En outre, dans votre cas, assurez-vous de remplacer tous les mots “okular” par votre mot “java”.

La plupart des réponses ont été inspirées par cet article .

Si vous avez besoin de relancer le stream stdin , vous pouvez le joindre au fichier pipe (FIFO), voir les détails ici .

Oui, il est possible d’extraire n’importe quelle sortie de processus avec les outils natifs de Solaris.

Une méthode consisterait à utiliser dtrace qui permet de suivre les processus même s’ils sont déjà saisis par un débogueur ou un outil similaire.

Ce script dtrace affichera une dtrace processus donnée:

 #!/bin/ksh pid=$1 dtrace -qn "syscall::write:entry /pid == $pid && arg0 == 1 / { printf(\"%s\",copyinstr(arg1)); }" 

Vous devriez passer l’identifiant de processus de l’application Java à tracer comme premier argument, par exemple. $(pgrep -f "java -jar SomeFile.jar") .

Remplacez arg0 == 1 par arg0 == 2 si vous voulez tracer stderr vs stdin .

Si vous voulez voir des caractères non affichables (en octal), vous pouvez utiliser cette version légèrement modifiée:

 #!/bin/ksh pid=$1 dtrace -qn "syscall::write:entry /pid == $pid && arg0 == 1 / { printf(\"%s\",copyinstr(arg1)); }" | od -c 

Une autre méthode native consiste à utiliser la commande truss . Le script suivant affichera toutes les écritures de votre processus sur tous les descripteurs de fichiers et inclura une trace détaillée complète pour stdout et stderr (3799 est votre identificateur de processus cible):

 truss -w1,2 -t write -p 3799 

dtrace: http://docs.oracle.com/cd/E18752_01/html/819-5488/gcgkk.html

treillis: http://docs.oracle.com/cd/E36784_01/html/E36870/truss-1.html#scrolltoc