2010-11-17 18 views
3

Je rencontre un comportement étrange lors de l'appel d'un script shell à partir d'un processus Java.Appel de script depuis java, signal sigpipe reçu

Process p = Runtime.getRuntime().exec("mybashscript.sh"); 
(new StreamGobblerThread(p.getInputStream())).start(); 
(new StreamGobblerThread(p.getErrorStream())).start(); 
p.waitFor(); 
returnValue = p.exitValue(); 

Le StreamGobblerThread a juste une méthode run() qui fait un

while(((inputStream.available>0) { inputStream.skip(available); } 

Environ 20% du temps, cela fonctionne, mais la plupart du temps le script échoue avec un code de retour de 141 tout de suite. D'après ce que j'ai trouvé sur google, 141 est un code de retour quand un SIGPIPE a été reçu.

Des idées?

+0

peut-être vous devriez imprimer les erreurs, ils pourraient vous donner un sens message d'erreur –

+0

'SIGPIPE' peut être provoqué par une sortie anticipée de' while' dans 'StreamGobblerThread'. Pour le vérifier, utilisez simplement 'run()' vide.Ajoutez une impression de débogage dans la boucle pour voir ce que 'available' est. Essayez de lire les données au lieu de sauter. – khachik

+0

il semble qu'il n'y ait pas d''erreur' autre que le code de retour du script, car il ne s'agit pas d'une exception Java. tout java semble savoir, c'est que le code de sortie du script – Will

Répondre

2

Je ne suis pas 100% sûr de ce que le problème, mais avant tout:

while(((inputStream.available>0) { inputStream.skip(available); } 

est pas valide. Ceci est dû au fait que inputStream.available() ne bloque pas, donc s'il n'a rien à lire immédiatement, il ne va rien lire du tout.

Vous êtes mieux d'avoir quelque chose comme ceci:

byte[] buf = new byte[8192]; 
int next; 
try { 
    while ((next = in.read(buf)) != -1) {} 
} catch (IOException e) { 
    throw new GroovyRuntimeException("exception while dumping process stream", e); 
} 

lecture() bloque donc, de cette façon, il continuera en fait la lecture jusqu'à ce que le courant soit bien fermé.

(Note: Ce code est de la mise en œuvre de consumeProcessOutput Groovy()

+0

bonne capture .. le thread StreamGobbler fermait réellement l'inputStream dès que rien de plus n'était disponible. mais puisque le script shell peut encore fonctionner, il le fermait prématurément. – Will

1

Cela signifie probablement une erreur de "tuyau cassé". Cela peut se produire lorsque l'un des processus connectés par le tuyau sort avant l'autre.

1

J'ai vu cela plusieurs fois dans ma vie et j'ai trouvé 2 solutions de contournement.

  1. Si vous voulez vraiment lire l'erreur et le flux de sortie séparément, exécutez la commande comme "/ bin/sh foo.sh 1>/tmp/out 2>/tmp/err" puis lire ces fichiers.
  2. S'il est bon pour vous de lire un mélange de stdout et stderr, utilisez ProcessBuilder comme suit:

ProcessBuilder b = new ProcessBuilder ("foo.sh"); b.redirectErrorStream (true); Processus p = b.start(); p.getInputStream(); // ..... etc.

maintenant lu dans le flux d'entrée qui contient à la fois stdout et stderr.

0

J'avais un problème similaire exécution du processus dans un thread qui est la méthode courir liraient le InputStream processus et ensuite appeler la méthode waitFor().

je me suis déplacé la lecture des processus INPUTSTREAM dans son propre fil comme l'OP a fait et n'était plus voir le code de sortie de tuyau cassé retourné.