7
votes

Java se bloque même si l'exécution du script est terminée

J'essaie d'exécuter un script de mon code Java qui ressemble à: xxx

L'exécution du script est terminée (c'est non plus n'est plus), mais Java est bloqué sur waitfor () méthode du processus !. Et oui, je lis la sortie et les flux d'erreur dans 2 threads distincts. Oui, ils sont joints à la fin (après waitfor () ).

Le script installe essentiellement quelques tours (comme 10 ou plus) et les configure. Donc, le script fonctionne un peu plus de 60 secondes.

Il ressemble à ce qui suit: xxx

assez choquante, si je mets la ligne suivante dans Le script (en haut), Java comprend le script est terminé et se termine parfaitement le processus. xxx

pour l'enregistrement, le script ne génère aucune sortie. Zéro caractères !. Donc, mettre la déclaration d'exécutant, il n'a aucun sens!

mais toujours, juste assez par magie, mettre l'énoncé Exec dans le script fait du travail Java !. Pourquoi ??

Comment puis-je éviter cette énoncé illogique Exec dans le script?

Si vous êtes intéressé par quel installer-script.sh ressemble à ce que: xxx

maintenant, pourquoi la commande exécutée dans le premier script est requise pour Java Savoir que le processus est terminé? Comment puis-je éviter cet exécuté ?, esp. Étant donné que le premier script ne produit aucune sortie.

En attente de réponses avec respiration battée!


3 commentaires

Essayez de faire un bref complet exemple de programme qui présente votre problème. Les gens pourraient être capables de repérer quelque chose de mal s'ils voient (et peut-être même essayer de courir) le code.


Le script est-il vraiment court? Peut-être que le script se termine trop vite? Pouvez-vous poster du code pour le script? Pouvez-vous publier le code Java qui exécute le script aussi? Pouvez-vous réduire à une simple classe exécutable avec un principal?


Édité la description comme suggéré par @gilles et @Romain. Espérer le meilleur!


7 Réponses :


0
votes

Si vous utilisez Linux / Unix, essayez pas consommant stdout / stardr.

La dernière fois que je devais exécuter un script externe à partir de Java, j'ai fini par avoir à vérifier le système d'exploitation et de fixer des threads de mangeur de sortie uniquement si sous Windows.


1 commentaires

Oh .. je dois consommer stdout / stardr, sinon cela se produira: Stackoverflow.com/Questtions/3425754/...



0
votes

Je voudrais également pomper également l'entrée standard. C'est une bonne idée de pomper les trois flux standard. Je ne peux pas l'expliquer, mais j'ai eu des problèmes similaires auparavant avec les processus suspendus, et c'est l'absence d'une pompe STDIN qui était le problème.


1 commentaires

Mais je suis toujours stupide-wondeur-frappé, de savoir comment EXPED aide Java identifier que le processus est terminé!



0
votes

Je n'ai pas essayé à Linux, mais j'ai rencontré ce problème dans Windows. Je pense que je devais fermer la norme du processus en cours de flux avant de finir.


0 commentaires

-1
votes

Vous ne pouvez pas écrire un script de Java et l'attendre. Vous devez exécuter l'interprète de ce script. Le cmdarray devrait commencer par "bash" et non "myscript.bash".


2 commentaires

Exécuter un script fonctionne directement bien s'il possède des autorisations exécutables et a le # approprié! ligne indiquant l'interprète (telle que / bin / sh).


Hein? In * Nix, les scripts sont des citoyens de première classe et se comportent comme d'autres processus.



1
votes

Une cause probable est que l'installation des packages démarre les processus d'arrière-plan qui empêchent l'un ou l'autre de vos tuyaux (stdout / stardr) ouverts. Par conséquent, vos discussions ne se termineront pas. Cela signifie que ces processus d'arrière-plan ne démontient pas correctement. Un démon approprié remplace son stdin / stdout / starr d'origine avec / dev / null ou un fichier journal après avoir terminé l'initialisation.


0 commentaires

8
votes

Je suppose que Java ne pense pas que le script est fini tant que les tuyaux qui lui ont transmis via STDIN / STDOUT / STDERR sont fermés par le sous-processus. Autrement dit, il n'y a plus de processus de lecteur actif sur stdin, plus de processus d'écrivain actif sur stdout / stardr.

Lorsque vous lisez sur un tuyau, vous ne recevez pas d'indication de fin de fichier avant qu'il n'y ait pas plus de processus em> qui ont le tuyau ouvert pour la sortie. Donc, si un processus de processus et le nouveau processus héritent d'une poignée de fichier ouverte, le processus d'origine se termine, il existe toujours un processus avec le fichier ouvert et un lecteur attendra toujours. P>

De même avec un tuyau que vous " Re écrit, vous ne recevrez pas de signal "tuyau cassé" tant que le dernier lecteur ferme le tuyau. P>

Ce problème se pose généralement lorsque votre script fourche des tâches d'arrière-plan (comme des services nouvellement installés) qui hériter de STDIN /stDout/sderr.

By Utiliser EXEC, vous enfreignez explicitement la chaîne d'héritage de ces tuyaux afin que les processus d'arrière-plan ne les utilisent pas. p>

Si sur Linux, vérifiez / proc / * / fd pour tous les nouveaux services et voir si leur stdin / stdout / stardr est le même tuyau que votre processus Java passe à votre script. P>

La même situation se produit souvent lorsque vous exécutez la / etc. /Init.d/xxx scripts: Ils se terminent normalement lorsque vous les exécutez à partir de la ligne de commande mais semblent suspendre lorsque vous les exécutez à partir d'une sorte de moniteur. p>

edit: strong> p>

vous dites que Le script d'installation contient la ligne: p>

exec 3>&1 >>/var/log/another-log.log 2>&1


2 commentaires

Merci@adrian. Cela semble probablement être la cause. D'une part, je suis tenté de marquer cela comme une réponse correcte, de l'autre, je ne suis pas vraiment sûr. Mon énoncé illogical Exec reste toujours !. J'attendrai un moment pour plus de réponses.


J'ai ajouté un peu plus sur la déclaration Exec.



0
votes

On dirait que vous compreniez des morceaux et des morceaux du problème, mais vous n'êtes toujours pas tout à fait d'obtenir la "grande image".

  1. Oui, il est possible d'appeler un script shell d'un programme Java. Facile, en fait! <= Vous le savez déjà.

  2. Oui, généralement, vous devriez être capable de voir tout ce qui est imprimé sur starr ou stdout.

  3. et oui, vous devriez être capable de rediriger stardr et / ou stdout dans un fichier.

  4. Votre problème est évidemment que vous ne voyez pas ce que vous attendez de voir, quand vous vous attendez à le voir. Ceci est normal, ceci est attendu ... et, dans le plus grand schéma de choses, c'est très souhaitable.

    Le problème central, je crois, est "E / S tampon".

    Le tampon est une bonne chose.

    Je vous encourage fortement à: 1. Créez un programme de test de ligne Java de ligne de commande simple et simple qui appelle un script shell. <= Vous devriez voir "Résultats attendus"

    1. élaborer le programme de test avec des threads. Selon la structure du programme, vous pouvez ou non obtenir des résultats attendus ".

    2. Substitue un programme C (ou un autre programme Java) pour le script shell <= Cela facilite l'utilisation "stardr", qui est ignorée, vs "stdout" Vous devriez également perdre le non-sens "EXED" - c'était un hareng rouge!

    3. expérimentez et voyez ce que vous apprenez.

      Bonne chance - et s'il vous plaît ne sautez pas juste à la première conclusion qui semble à mi-chemin plausible. Testez toujours vos théories.

      PS: Et répétez mon mantra: "Le tampon d'E / S est bon"; -)

      pps:

      Q: Cette question n'a été visionnée que 38 fois jusqu'à présent!

      A: "Vous devez apprendre patience, jeune sauterelle"; -)

      Q: C'est un peu critique pour moi!

      A: "L'humilité devez-vous apprendre aussi"; -)


0 commentaires