IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

Shell depuis java et IOException


Sujet :

Entrée/Sortie Java

  1. #1
    Membre à l'essai
    Inscrit en
    Octobre 2006
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 20
    Points : 12
    Points
    12
    Par défaut Shell depuis java et IOException
    Bonjour,
    J'ai créé mon propre shell sur un serveur linux que je dois appeler depuis une application web sous tomcat.
    J'utilise l'API d'adiguba concernant les shell qui, en principe, règle les pbs d'entrée-sortie des flux.
    J'ai encapsulé l'appele de ce shell danjs un thread, comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    package fr.britair.analyzerPVE.thread;
     
    import java.io.IOException;
     
    import org.apache.log4j.Logger;
     
    import com.developpez.adiguba.shell.ProcessConsumer;
    import com.developpez.adiguba.shell.Shell;
     
    import fr.britair.analyzerPVE.constants.Constants;
     
    public class ThreadGenerationPVE implements Runnable{
     
    	/** Logger. */
    	private static Logger log = Logger.getLogger(ThreadGenerationPVE.class);
     
    	private long tempsAttenteAvantVerificationPVEGenere;
     
    	String[] parametresFormatagePVE = new String[9];
     
    	public String[] getParametresFormatagePVE() {
    		return parametresFormatagePVE;
    	}
     
    	public void setParametresFormatagePVE(String[] parametresFormatagePVE) {
    		this.parametresFormatagePVE = parametresFormatagePVE;
    	}
     
    	public void run() {
    //		MainClientSafetyPveGenerator.main(getParametresFormatagePVE());
    		StringBuilder stringBuilder = new StringBuilder();
    		stringBuilder.append(Constants.RUN_SHELL_PVE);
    		stringBuilder.append(" ");
    		for (int i = 0; i < getParametresFormatagePVE().length; i++) {
    			if (i!=5)
    				stringBuilder.append(getParametresFormatagePVE()[i]);
    			else
    				stringBuilder.append("\""+getParametresFormatagePVE()[i]+"\"");
    			if (i != getParametresFormatagePVE().length-1)
    				stringBuilder.append(" ");
    		}
    		log.error("COMMANDE SHELL = " +stringBuilder.toString());
    		Shell shell = new Shell();
    		ProcessConsumer process = shell.command(stringBuilder.toString());
    		try {
    			int result = process.consume();
    		} catch (Exception e) {
    			log.error("IOException dans l'execution du Shell " + Constants.RUN_SHELL_PVE);
    			e.printStackTrace();
    		}
    	}
     
    	public long getTempsAttenteAvantVerificationPVEGenere() {
    		return tempsAttenteAvantVerificationPVEGenere;
    	}
     
    	public void setTempsAttenteAvantVerificationPVEGenere(
    			long tempsAttenteAvantVerificationPVEGenere) {
    		this.tempsAttenteAvantVerificationPVEGenere = tempsAttenteAvantVerificationPVEGenere;
    	}
     
    }
    Puis dans mon appli web, j'appelle ce thread tout simplement avec la méthode
    'start' du thread.
    Le shell est censé me générer ou pas des fichiers XML.
    Il m'arrive parfois dans mon code d'iterer plusieurs fois l'appel à ce thread qui m'execute mon Shell linux, de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    for(Object[] objects : listeRoutes)
    {
     
    						ThreadGenerationRoute threadGenerationRoute = new ThreadGenerationRoute();
    						threadGenerationRoute.setParametresGenerationRoute(parametresGenerationRoute);
    						Thread t = new Thread(threadGenerationRoute);
    						/** Appel du gestionnaire PVE **/
    						log.error("##### APPEL DU GESTIONNAIRE DE GENERATION D'UNE ROUTE SECOURS pour la Route " + aeroportDepart+"/"+aeroportArrivee+"/"+groupeAvion+"/"+route);
    						t.start();
    						try {
    							int nb=0;
    							//On vérifie si le fichier est arrivé toutes les 50 sec.
    							while(!verifiePresenceFichierLogSecoursGenere(fichierGenere) && nb<12) {
    								log.error("##### On attend "+(50000)/1000+" sec. de plus avant de verifier si le fichier XML de la route est là");
    								Thread.sleep(50000);
    								nb++;
    							}
    						} catch (InterruptedException e1) {
    							throw new CommonsRuntimeException("InterruptedException dans la méthode sleep du Thread courant d'appel à la génération de route ");
    						}
    //						log.error("## INTERRUPTION DE L'APPEL A LA GENERATION DE LA ROUTE ##");
    						t.interrupt();
    }
    //fin for
    }

    Or il se trouve que j'ai toujours des IOException lorsque j'appelle ce thread plusieurs fois avec mon itération de la boucke for.
    Je pensais que l'API d'adiguba réglait les pbs d'I/O mais apparemment j'ai tjs des pbs d'I/O, ce qui a pour effet d'arreter le serveur TOMCAT lorsque cette Exception est rencontrée.
    Quelq'un aurait il une idée ?
    Merci.

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Tu obtiens quoi comme exception exactement ?

    a++

  3. #3
    Membre à l'essai
    Inscrit en
    Octobre 2006
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 20
    Points : 12
    Points
    12
    Par défaut
    Salut,
    tout d'abord merci pour l'explication de ton API sur le site.
    En fait l'exception est rencontrée dans la méthode "consume" comme dans mon code ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    try {
    	int result = process.consume();
    } catch (Exception e) {
    	log.error("IOException dans l'execution du Shell " + Constants.RUN_SHELL_PVE);
    	e.printStackTrace();
    }
    Mais ceci est aléatoire car lors de mes tests d'intégration je n'ai pas réussi à reproduire l'exception à chaque fois.

    Pour être plus précis, j'ai 2 shells différents que j'ai encapsulé chacun dans un e classe thread, comme je l'ai expliqué.
    L'appel à un de ces shell se fait de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    ThreadGenerationRoute threadGenerationRoute = new ThreadGenerationRoute();
    						threadGenerationRoute.setParametresGenerationRoute(parametresGenerationRoute);
    Thread t = new Thread(threadGenerationRoute);
    /** Appel du gestionnaire PVE **/
    log.error("##### APPEL DU GESTIONNAIRE DE GENERATION D'UNE ROUTE SECOURS pour la Route " + aeroportDepart+"/"+aeroportArrivee+"/"+groupeAvion+"/"+route);
    	t.start();
    	try {
    	int nb=0;
    	//On vérifie si le fichier est arrivé toutes les 50 sec.
    							  while(!verifiePresenceFichierLogSecoursGenere(fichierGenere) && nb<12) {
    								log.error("##### On attend "+(50000)/1000+" sec. de plus avant de verifier si le fichier XML de la route est là");
    	Thread.sleep(50000);
    	nb++;
    	}
    	} catch (InterruptedException e1) {
    	throw new CommonsRuntimeException("InterruptedException dans la méthode sleep du Thread courant d'appel à la génération de route ");
    	}
    //	log.error("## INTERRUPTION DE L'APPEL A LA GENERATION DE LA ROUTE ##");
    	t.interrupt();
    Je vais donner quelques petites explications :
    Ce code est dans une classe d'action STRUTS. J'appelle le shell en instanciant la classe thread contenant ton API d'execution de mon shell puis j'appelle la méthode 'start' de ce thread. Ce shell est censé me généré un fichier XML. Ce calcul est tyrès long, donc je vérifie si ce fichier XML est arrivé toutes les 50 secondes (boucle 'while'). Si le fichier est arrivé interruption du thread d'appel du shell.
    Après l'arrivée de ce fichier XML, je fais une verification. En fonction de cette vérification, je dois appeler ou pas 'X' fois le 2ème SHELL encapsulé dans un thread. C'est le code que j'ai posté au début. Et c'est là que je rencontre l'IOException.

    Je n'ai pas besoin des flux de sorties, erreurs ... évoqués dans ton API.
    Y aurait-il un probleme avec l'écriture dans le fichier "catalina.out" de sortie standard de TOMCAT.

    Merci beaucoup pour ton idée.
    A +.

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par gbruno
    En fait l'exception est rencontrée dans la méthode "consume" comme dans mon code ci-dessous :
    Mais en fait il me faudrais surtout le stacktrace de l'exception qui est remonté...

    Citation Envoyé par gbruno
    Ce shell est censé me généré un fichier XML. Ce calcul est tyrès long, donc je vérifie si ce fichier XML est arrivé toutes les 50 secondes (boucle 'while'). Si le fichier est arrivé interruption du thread d'appel du shell.
    Ton exception peut venir de là : lorsqu'elle reçoit une interruption la méthode consume() est censé remonté une InterruptedIOException...

    Citation Envoyé par gbruno
    Je n'ai pas besoin des flux de sorties, erreurs ... évoqués dans ton API.
    Y aurait-il un probleme avec l'écriture dans le fichier "catalina.out" de sortie standard de TOMCAT.
    Normalement non, mais si le programme appelé écrit un grand nombre de donnée cela peut être gênant. Dans ce cas il suffit de désactiver les traces :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int result = process.output().error().consume();
    a++

  5. #5
    Membre à l'essai
    Inscrit en
    Octobre 2006
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 20
    Points : 12
    Points
    12
    Par défaut
    Mais en fait il me faudrais surtout le stacktrace de l'exception qui est remonté...
    Pour l'instant je ne peux te proposer de stacktrace car je vide le fichier de sortie de catalina.out lorsque je redémarre le serveur Tomcat or à chaque fois qu'est rencontrée cette Exception ça a pour effet d'arreter le serveur Tomcat.
    Je peux te donner le stacktrace dès que je rencontrerai l'erreur.


    Ton exception peut venir de là : lorsqu'elle reçoit une interruption la méthode consume() est censé remonté une InterruptedIOException...
    Dans ce cas crois-tu que je peux lever l'exception en supprimant la ligne
    après la boucle while qui teste toutes les N secondes si le fichier est arrivé ??
    Le fait de ne pas faire d'"interrupt" sur le thread qui appelle le shell que j'ai créé. Il sera toujours vivant non ? Ce n'est pas grave ?

    int result = process.output().error().consume();
    Cette ligne n'aura aucun effet sur le fichier de sortie de Tomcat ? Car j'ai besoin des traces de Tomcat ...
    Penses-tu que cette ligne de code peux résoudre mon probleme aussi ?
    Merci beaucoup pour ton aide.
    A +

  6. #6
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par gbruno
    Dans ce cas crois-tu que je peux lever l'exception en supprimant la ligne
    après la boucle while qui teste toutes les N secondes si le fichier est arrivé ??
    Le fait de ne pas faire d'"interrupt" sur le thread qui appelle le shell que j'ai créé. Il sera toujours vivant non ? Ce n'est pas grave ?
    La méthode consume() renvoi un InterruptedException si elle reçoit un interrupt pendant son traitement.

    Donc tu as deux solutions :
    • Soit tu continues à envoyer l'interrupt pour arrêter "violemment" le process et tu "ignores" l'InterruptedException.
    • Soit tu supprimes l'interrupt et dans ce cas le thread sera terminé à la fin du process que tu lances (consume() se termine en même temps que le process fils).


    La question est surtout de savoir pourquoi tu le lances dans un thread et que tu vérifies le fichier en parallèle...

    Ne serait-il pas préférable d'attendre simplement la fin de consume() et de traiter le fichier une fois que le process est complètement terminée ?

    Citation Envoyé par gbruno
    Cette ligne n'aura aucun effet sur le fichier de sortie de Tomcat ? Car j'ai besoin des traces de Tomcat ...
    Non.
    Par défaut consume() copie les flux de sortie du process lancé dans les flux de sortie de l'application Java, qui correspondent au fichier "catalina.out" sous Tomcat. Cette ligne indique seulement que les flux de sortie et d'erreur du process doivent être ignoré au lieu d'être réécrit sur la sortie...

    Citation Envoyé par gbruno
    Penses-tu que cette ligne de code peux résoudre mon probleme aussi ?
    Non : cela se contentera de ne pas écrire la sortie du process dans le fichier de sortie de Tomcat, et donc potentiellement limité la taille des logs si ton process génère un grand nombre de trace...


    a++

  7. #7
    Membre à l'essai
    Inscrit en
    Octobre 2006
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 20
    Points : 12
    Points
    12
    Par défaut
    Donc tu as deux solutions :

    * Soit tu continues à envoyer l'interrupt pour arrêter "violemment" le process et tu "ignores" l'InterruptedException.
    * Soit tu supprimes l'interrupt et dans ce cas le thread sera terminé à la fin du process que tu lances (consume() se termine en même temps que le process fils).
    Je vais opter pour la suppression de l'interrupt plutôt.

    La question est surtout de savoir pourquoi tu le lances dans un thread et que tu vérifies le fichier en parallèle...

    Ne serait-il pas préférable d'attendre simplement la fin de consume() et de traiter le fichier une fois que le process est complètement terminée ?

    J'ai fait comme ça, car en fait le shell linux appelle lui-même une appli écrite en java sous forme de jar executable par un autre collègue. Or dans sa version 1 de l'appli java, le thread responsable de la génération du fichier XML ne rend jamais la main au thread courant appelant. Si bien que je ne peux "avoir la main" une fois que le fichier XML est généré. Voilà pourquoi je fais une vérification de la présence du fichier XML toutes les N secondes. Je n'ai pas d'autres solutions pour l'instant que de faire comme ça.

    Quoiqu'il en soit, je vais supprimer tous les "interrupt" qui seraient à l'origine de mon IOException ainsi que rajouter la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int result = process.output().error().consume();
    Je posterai un nouveau message si jamais je rencontre à nouveau l'IOException en t'envoyant le stacktrace complet.
    Merci beaucoup pour ton aide.
    A +.

  8. #8
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par gbruno
    J'ai fait comme ça, car en fait le shell linux appelle lui-même une appli écrite en java sous forme de jar executable par un autre collègue. Or dans sa version 1 de l'appli java, le thread responsable de la génération du fichier XML ne rend jamais la main au thread courant appelant.
    Donc si je comprend bien le programme que tu lances ne se termine jamais ???

    Dans ce cas l'interrupt() est bien nécessaire pour tenter de tuer le process...

    a++

  9. #9
    Membre à l'essai
    Inscrit en
    Octobre 2006
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 20
    Points : 12
    Points
    12
    Par défaut
    Oui mais ça se mord la queue, car effectivement il faudrait un interrupt(), mais c'est, apparemment, ça qui me provoque l'IOException ??!?

  10. #10
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par gbruno
    Oui mais ça se mord la queue, car effectivement il faudrait un interrupt(), mais c'est, apparemment, ça qui me provoque l'IOException ??!?
    Oui mais c'est normal : si tu interrompt le traitement cela remonte une exception...


    Ce qui n'est pas normal c'est que le process que tu lances ne s'arrête pas normalement une fois qu'il a fini (au fait comme fais-tu pour savoir que la génération du fichier est terminé ?)

    a++

  11. #11
    Membre à l'essai
    Inscrit en
    Octobre 2006
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 20
    Points : 12
    Points
    12
    Par défaut
    Je suis d'accord avec toi mais la v2 du jar executable de mon collègue que j'appelle via le shell devrait régler ce pb.
    Je devrais reprendre la main sur le process une fois qu'il sera terminé.

    Pour verifier que la génération du fichier est terminée, c'est simple je connais le nom du fichier qui doit être généré ainsi que le repertoire de dépot. Donc pas de pb.

    Et sinon, le fait de ne pas faire d'interrupt() sur le thread qui appellera le shell, quelle conséquence ?
    Merci.

  12. #12
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par gbruno
    Pour verifier que la génération du fichier est terminée, c'est simple je connais le nom du fichier qui doit être généré ainsi que le repertoire de dépot. Donc pas de pb.
    Oui mais comment peux-tu être sûr que le fichier est généré dans sa totalité ??

    Citation Envoyé par gbruno
    Et sinon, le fait de ne pas faire d'interrupt() sur le thread qui appellera le shell, quelle conséquence ?
    Rien : le thread s'exécutera jusqu'à la fin du process que tu lances... mais si ce dernier ne s'arrête pas tout seul tu aura un thread et un process qui tourneront pour rien...

    a++

Discussions similaires

  1. Réponses: 3
    Dernier message: 10/01/2008, 12h08
  2. [Système]commandes linux / unix depuis java
    Par msiramy dans le forum API standards et tierces
    Réponses: 12
    Dernier message: 20/03/2007, 11h29
  3. [débutant]lancement d'une commande Unix ou LInux depuis Java
    Par msiramy dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 30/09/2005, 18h10
  4. [Info] Appeler une fonction Ada95 depuis Java
    Par mmathieu dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 15/09/2005, 09h42
  5. [debutant] créer un alias odbc depuis java
    Par chassonj dans le forum JDBC
    Réponses: 5
    Dernier message: 08/07/2004, 15h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo