[java] Exécuter une appli ext. sous Solaris

Alors voilà, deux problèmes distincts, mais je suppose qu’il vaut mieux faire un post unique. Je vous expose ça:

Problème 1: je fais un pti programme Client-Serveur qui doit permettre de dialoguer entre une station Solaris (serveur) et plusieurs stations WINNT (clients donc). Les messages passent, pas de souci, j’échange des objects sans problème via sockets.

MAIS: je veux aussi pouvoir lancer une appli distante: depuis mon winnt dire à mon Solaris: « lance le programme zouzou ». Et là l’execution foire. Sous la forme suivante:

INFO: Action received: commandLine=a2t start (<< ça c'est mon logger qui me dit que la commande "a2t start" a été reçue) java.io.IOException: a2t: not found &nbsp; &nbsp; &nbsp; &nbsp;at java.lang.UNIXProcess.forkAndExec(Native Method) &nbsp; &nbsp; &nbsp; &nbsp;at java.lang.UNIXProcess.<init>(UNIXProcess.java:56) &nbsp; &nbsp; &nbsp; &nbsp;at java.lang.Runtime.execInternal(Native Method) &nbsp; &nbsp; &nbsp; &nbsp;at java.lang.Runtime.exec(Runtime.java:566) &nbsp; &nbsp; &nbsp; &nbsp;at java.lang.Runtime.exec(Runtime.java:428) &nbsp; &nbsp; &nbsp; &nbsp;at java.lang.Runtime.exec(Runtime.java:364) &nbsp; &nbsp; &nbsp; &nbsp;at java.lang.Runtime.exec(Runtime.java:326) &nbsp; &nbsp; &nbsp; &nbsp;at transmitter.Client.cmdExec(Comm.java:197) &nbsp; &nbsp; &nbsp; &nbsp;at transmitter.Client.treatMessage(Comm.java:163) &nbsp; &nbsp; &nbsp; &nbsp;at transmitter.Client.run(Comm.java:181)

Mon code qui exécute les processes ressemble à ça:

public void cmdExec(String cmdline) { &nbsp; &nbsp; &nbsp;try { &nbsp; &nbsp; &nbsp; &nbsp; String line; &nbsp; &nbsp; &nbsp; &nbsp; Process p = Runtime.getRuntime().exec(cmdline); &nbsp; &nbsp; &nbsp; &nbsp; BufferedReader input = &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;new BufferedReader &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(new InputStreamReader(p.getInputStream())); &nbsp; &nbsp; &nbsp; &nbsp; while ((line = input.readLine()) != null) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.println(line); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; input.close(); &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp;catch (Exception err) { &nbsp; &nbsp; &nbsp; &nbsp; err.printStackTrace(); &nbsp; &nbsp; &nbsp;} &nbsp; }

Alors je sais pas trop comment lancer un process externe autrement moi… Je suis preneur de toute piste, parce que cette histoire m’emmerde bien… C’est un peu le but de mon prog de lancer une appli distante…

Problème 2:
Du coup sous mon winnt des fois je lance aussi un server (pour tester en local), enfin je compile et je lance… Mais justement ça foire. Mon programme server écoute sur un port, mais le problème c’est qu’une fois le programme fermé, l’écoute sur le port est pas fermée (j’ignore pourquoi) et du coup quand je compile une deuxieme fois, il plante à l’écution, une jolie: java.net.BindException: Address already in use: JVM_Bind.

Alors j’aimerais pouvoir killer ce truc qui m’écoute sur mon port parce que là du coup je suis obligé de faire un jar, de l’uploader par ftp sur ma machine Solaris et puis de la lancer dans un term. Ce qui est un peu relou.

Merci beaucoup d’avance… ça fait un moment que je bloque sur ces deux conneries. Je suis à l’écoute si vous avez besoin de plus de précisions.

:stuck_out_tongue:

Salut,

  • Pour ton premier problème tu sembles vouloir lancer « a2t start », or il essaie d’exécuter a2t donc déjà il y a une erreur. Essaie plutôt cet exec là :

exec(String[] cmdarray)

avec a2t et start dans deux cases du tableau.

Mais ce n’est pas le gros du problème: il ne trouve pas ton programme a2t.
Est-il dans le path ?

  • Pour le second problème si tu travailles en socket, tu dois avoir un objet ServerSocket qui a une méthode close qui ferme la connection sur le port. à toi de trouver comment fermer ton serveur proprement avec cette méthode. En espérant que ça t’aide :stuck_out_tongue:

[quote name=‹ gaelh › date=’ 23 Jun 2005, 10:19’]Salut,

  • Pour ton premier problème tu sembles vouloir lancer « a2t start », or il essaie d’exécuter a2t donc déjà il y a une erreur. Essaie plutôt cet exec là :

exec(String[] cmdarray)

avec a2t et start dans deux cases du tableau.[/quote]
Oui mais en fait a2t comme a2t start marchent (mais ne font pas le même traitement). Mais oui, tu soulèves un point important, j’avais pas fait trop attention, j’essaierai ta méthode quand ça marchera :stuck_out_tongue:

[quote name=‹ gaelh › date=’ 23 Jun 2005, 10:19’]Mais ce n’est pas le gros du problème: il ne trouve pas ton programme a2t.
Est-il dans le path ?[/quote]
Oui oui, quand je lance la commande depuis le term ça marche sans souci, a2t, a2t start, tout marche.

Oui, il faut que je fasse ça, ça doit venir du fait que 3/4 du temps je quitte comme un porc il faudrait que j’arrive à chopper l’événement de fermeture et que je rajoute le close() mais le souci est aussi que très souvent ce sont des exceptions qui bloquent mon prog donc je vais pas mettre des close() sur tous mes catches d’exception… Puis depuis ce matin c’est tjrs pas fermé l’écoute sur le port…

Merci !

[quote name=‘LeGzo’ date=’ 23 Jun 2005, 10:43’]…
Oui, il faut que je fasse ça, ça doit venir du fait que 3/4 du temps je quitte comme un porc il faudrait que j’arrive à chopper l’événement de fermeture et que je rajoute le close() mais le souci est aussi que très souvent ce sont des exceptions qui bloquent mon prog donc je vais pas mettre des close() sur tous mes catches d’exception… Puis depuis ce matin c’est tjrs pas fermé l’écoute sur le port…

Merci !
[right][post=“371088”]<{POST_SNAPBACK}>[/post][/right][/quote]

Tu peux mettre le close dans un finally apres les catch.

Pour lancer ton programme distant, tu ne devrais pas lui donner le path absolu vers le programme en question ?

Parce que même si tes variables d’environnement permettent de lancer le programme en question où que tu sois en mode terminal, les variables d’environnement ne seront pas les mêmes pour le process lancé par java. Enfin, c’est le problème que j’ai eu récemment avec une application qui faisait plus ou moins la même chose sous OS X.

[quote name=‹ Funestelame › date=’ 23 Jun 2005, 13:13’]Pour lancer ton programme distant, tu ne devrais pas lui donner le path absolu vers le programme en question ?

Parce que même si tes variables d’environnement permettent de lancer le programme en question où que tu sois en mode terminal, les variables d’environnement ne seront pas les mêmes pour le process lancé par java. Enfin, c’est le problème que j’ai eu récemment avec une application qui faisait plus ou moins la même chose sous OS X.
[right][post=« 371180 »]<{POST_SNAPBACK}>[/post][/right][/quote]
Oui c’est pas con ça… mais bon ça va pas être coton de récupérer mon path absolu… c’est un peu le bordel cette affaire avec une dizaine d’users qui pointent vers le même fichiers via des liens… uhh :stuck_out_tongue:

Bon enfin peut être que ça foire à cause de ça…

Tiens je vais essayer de balancer un ls comme commande… J’ai pas testé ça.

edit: oui bah le « ls » il s’exécute sans problème… et ça ça m’arrange pas du tout…
Si je peux pas chopper le path absolu, y’a pas un moyen de chopper mes variables d’environnement comme si j’étais en remote shell?

Thx

Mouais c’est ballot j’arrive pas à lui faire faire un export, ni à lui faire sourcer mon .profile… Il me dit que les commandes export et . ne sont pas connues…

C’est un petit peu embettant cette affaire.

Bon, ok ça avance, mais je suis à nouveau confronté à un truc un peu relou:

Alors reprenons: j’arrive à balancer des lignes de commandes de ma machine WinNT à ma machine Solaris. Cette dernière la lit mais n’a pas de notion d’environnement, c’est à dire qu’un “ls -l” ou un “cal” ca marche mais pas “export”, pas “.”.

Je veux lui faire exécuter plusieurs fichiers .sh, le problème est qu’apparemment il faut fournir à la classe Proc un binaire sinon il peut pas l’exécuter. Du coup, je tente un “ksh(ou bash) monshell.sh” et ça ça marche.

OR le truc que je lance prend la main on dirait et du coup mon serveur n’est plus receptif aux autres commandes que je peux envoyer (le truc en .sh tourne tant qu’on le stoppe pas).

Quand je ferme mon serveur et que je fais un “ps” j’ai deux processes “bash” (ou un bash + un ksh) et j’ai les processes lancés par mon shell…

Donc je sais pas du tout comment faire pour rester en boucle d’écoute même après avoir envoyé ma commande… (j’ai tenté de la lancer en tache de fond, mais ça marche pas…).

Help, i need somebody!! help not just anybody… Non sans déc chuis dans le caca :’(

Je peux voir le code de ton serveur ?

Tu as bien un truc de se genre :

[code]public class Serveur implements Runnable
{
   public void start()
   {
       thread = new Thread(this);
       thread.start();
   }

   public void stop()
   {
       if (thread != null) {
           thread = null;

           try {
               socketServeur.close();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }

   public void run()
   {
       try {
           socketServeur = new ServerSocket(PORT);

           Thread thisThread = Thread.currentThread();
           while (thread == thisThread) {
               new ConnectionIn(socketServeur.accept());
           }
       } catch (IOException e) {
           ui.error(“Connection fermée”);
       }
   }
}[/code]

C’est un peu dans ce style, mais c’est pas foutu pareil:

j’ai ma classe de communication qui étend Thread et qui est bloquée sur une boucle d’attente de connection (socketServeur.accept()) qui ensuite me crée une instance de ma classe Client qui elle aussi étend Thread.

Jte paste l’essentiel:

[code]public class Comm extends Thread {

private final int port = 19999;
private Vector listClients;
private ServerSocket sock = null;
private boolean listening = false;
int num = 0;

public Comm() {

 listClients = new Vector();
 try {
 sock = new ServerSocket(port);
 }
 catch (IOException ioException) {
 System.out.println("!!Could not listen on port: " + port);
 ioException.printStackTrace();
 System.exit(1);
 }
 
 listening = true;
}

public void run() {

 while (listening) {  
 try {
   this.newClient(sock.accept());
   num++;
 }
 catch (Exception ex1) {[CODE]
   System.out.println(ex1.toString());

&nbsp;}
&nbsp;// Waiting next client.

 }
}

protected void newClient(Socket socket) throws IOException, ClassNotFoundException {

 
 System.out.println("\n>>Connexion received from : " + socket.getInetAddress().getHostAddress() +
   “:” + socket.getPort());
 num = listClients.size();
 Client currentClient = new Client(socket, num, “login”, listClients);
 
 listClients.addElement(currentClient);
 currentClient.start(); // starting the thread.
 
}
}[/code]

Le run() de ma classe Client c’est ça:

public void run() { &nbsp;this.online = true; &nbsp; &nbsp;while (true) { &nbsp; &nbsp;if (this.online) { &nbsp; &nbsp; &nbsp; &nbsp;try { &nbsp; &nbsp;// wait for a message &nbsp; &nbsp;Object message = entree.readObject(); &nbsp; &nbsp;treatMessage((AbstractMessage) message); &nbsp; &nbsp;} &nbsp; &nbsp;catch (IOException ioException) { &nbsp; &nbsp;online = false; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;catch (ClassNotFoundException cNFE) { &nbsp; &nbsp;cNFE.printStackTrace(); &nbsp; &nbsp;} &nbsp;} &nbsp;} }

et ma commande qui exécute mon process externe quand je reçois un AbstractMessage que je sous-cast en Action (une classe à moi) la voici:

[edit2]: je l’ai déjà collée plus haut, je vais polluer le topic, voir dans mon premier post cmdExec(); elle a pas bougé;

was passiert?
(arf désolé ça indente mal à cause des tab…)

C’est quoi le code qu’il y a dans la fonction “treatMessage” ((AbstractMessage) message); ?

[quote name=‹ CaML › date=’ 28 Jun 2005, 13:42’]C’est quoi le code qu’il y a dans la fonction « treatMessage » ((AbstractMessage) message);  ?
[right][post=« 372380 »]<{POST_SNAPBACK}>[/post][/right][/quote]
Oh le chameau! Il s’est inscrit à Cafzone pour l’occasion :stuck_out_tongue: Salut dude :stuck_out_tongue:

Le code c’est un truc comme ça:

private void treatMessage(AbstractMessage m) { &nbsp; &nbsp;if (m instanceof Message) &nbsp;{ &nbsp;Message message = (Message)m; &nbsp;// &nbsp;System.out.println(">>Message received: flag=" + message.getFlag() + " & content=" + message.getContent()); &nbsp;[[[[ traitement si c'est un Message ]]]] &nbsp;} else if (m instanceof Action) { &nbsp;Action action = (Action)m; &nbsp;System.out.println("\n>>Action received: commandLine = " + action.getCmdLine()); &nbsp;cmdExec(action.getCmdLine()); &nbsp;} else if (m instanceof TransFile) { &nbsp;TransFile file = (TransFile)m; &nbsp;System.out.println("\n>>File received: commandLine = " + file.getFileName()); &nbsp;[[[[ traitement si c'est une File ]]]] &nbsp; &nbsp;} else { &nbsp;System.out.println("\n>> Message inconnu reçu"); &nbsp;} &nbsp; &nbsp; }

c’est moi :stuck_out_tongue:

sinon, en fait si tu pouvais paster le code qui lance la commande qui doit se trouver dans cmdExec a mon avis, non?

public void a2tGo() { &nbsp;Action act = new Action(2, "ksh a2t.sh go"); &nbsp;act.send(client.getOutput()); }

voilà ce que je fais… c’est pourtant pas bien compliqué!

Ensuite le serveur le reçoit: hop c’est une action, je lis la ligne de commande, je l’exécute. Ca marche, mais c’est bloquant…

Ce que je voulais c’est le code de cette fonction.
Tu dois sauvegarder quelque part le flux de sortie de la console pour l’envoyer vers le client nan?

Ca serait pas la que ca pose pb, dans le cas ou la commande que t’as lancée a pas fini de s’executer ?

[quote name=‘CaML’ date=’ 28 Jun 2005, 14:55’]Ce que je voulais c’est le code de cette fonction.
Tu dois sauvegarder quelque part le flux de sortie de la console pour l’envoyer vers le client nan?

Ca serait pas la que ca pose pb, dans le cas ou la commande que t’as lancée a pas fini de s’executer ?
[right][post=“372427”]<{POST_SNAPBACK}>[/post][/right][/quote]
Je l’ai pas encore fait l’envoi du flux console vers le client, pour l’instant ça affiche uniquement sur la sortie standard de mon terminal…

Pour le code de cmdExec() tu l’as en haut dans mon premier post.

oups, desolé, j’avais po vu.

Essaye de foutre cela dans un Thread a part. A mon avis le pb viens de la.
genre:

[code]public class ExecCmd extends Thread {

private String cmd;

public ExecCmd(String cmd) {
 this.cmd = cmd;
}

public void run() {
    try {
       String line;
       Process p = Runtime.getRuntime().exec(this.cmd);
       BufferedReader input =
          new BufferedReader
          (new InputStreamReader(p.getInputStream()));
       while ((line = input.readLine()) != null) {
          System.out.println(line);
       }
       input.close();
    }
    catch (Exception err) {
       err.printStackTrace();
    }
 }[/code]

et tu lance avec

ExecCmd cmd = new ExecCmd(action.getCmdLine()); cmd.start();

Hé ouais j’y avais pensé mais j’aime pas ça, enfin je vais tester, mais je le sens pas… genre chaque Thread va me créer un process bash ou ksh et je vais me retrouver avec plein de processes qui arriveront pas à dialoguer entre eux je pense… .enfin ça va pas être coton…

Je vais faire ça néanmoins et si ça marche je t’épouse. (ou non).

ouais ou pas :stuck_out_tongue:

Ouais bin si hein, tu peux réserver la salle des fêtes et acheter une robe cocotte. :stuck_out_tongue:

Ca marche!!

Bon c’est magnifique cette histoire, ca me fait grandement avancer. Thx CaML. C’est impeccable.