Certaines commandes Unix échouent avec “… not found”, lorsqu'elles sont exécutées via Java à l'aide de JSch




shell ssh (2)

Le canal "exec" dans le JSch (à juste titre) n'attribue pas de pseudo terminal (PTY) pour la session. En conséquence, un ensemble différent de scripts de démarrage est (peut-être) généré (en particulier pour les sessions non interactives, le .bash_profile n'est pas généré). Et / ou différentes branches dans les scripts sont prises, en fonction de l'absence / présence de la variable d'environnement TERM . Donc, l'environnement peut différer de la session interactive que vous utilisez avec votre client SSH.

Donc, dans votre cas, le PATH est probablement défini différemment; et par conséquent l'exécutable air ne peut pas être trouvé.

Pour vérifier qu’il s’agit bien de la cause, désactivez l’allocation de pseudo-terminaux dans votre client SSH. Par exemple, dans PuTTY, il s'agit de Connexion> SSH> TTY> Ne pas allouer de pseudo-terminal . Ensuite, allez à Connexion> SSH> Commande à distance et entrez votre commande air ... Vérifiez la session> Fermer la fenêtre à la sortie> Jamais et ouvrez la session. Vous devriez obtenir la même erreur "air introuvable" .

Façons de résoudre ce problème, par ordre de préférence:

  1. Corrigez la commande pour qu'elle ne s'appuie pas sur un environnement spécifique. Utilisez un chemin complet pour air dans la commande. Par exemple:

    /bin/air sandbox run <graph-path>

    Si vous ne connaissez pas le chemin complet, sur les systèmes * nix courants, vous pouvez utiliser which air commandement which air dans votre session SSH interactive.

  2. Corrigez vos scripts de démarrage pour que PATH identique pour les sessions interactives et non interactives.

  3. Essayez d’exécuter le script de manière explicite via le shell de connexion (utilisez le commutateur --login avec les shells * nix courants):

    bash --login -c "air sandbox run sandbox run <graph-path>"
  4. Si la commande elle-même repose sur une configuration d'environnement spécifique et que vous ne pouvez pas corriger les scripts de démarrage, vous pouvez modifier l'environnement dans la commande elle-même. La syntaxe dépend du système distant et / ou du shell. Dans les systèmes * nix communs, cela fonctionne:

    String command="PATH=\"$PATH;/path/to/air\" && air sandbox run <graph-path>";
  5. Une autre approche (non recommandée) consiste à forcer l'allocation de pseudo-terminaux pour le canal "exec" à l'aide de la méthode .setPty :

    Channel channel = session.openChannel("exec");
    ((ChannelExec)channel).setPty(true);

    L'utilisation du pseudo-terminal pour automatiser l'exécution d'une commande peut entraîner des effets secondaires désagréables. Voir par exemple Existe-t-il un moyen simple de supprimer les valeurs indésirables qui apparaissent lorsque vous utilisez SSH à l'aide de la bibliothèque Paramiko de Python et extrayez la sortie de la CLI d'une machine distante?

Pour des problèmes similaires, voir

  • Certaines commandes Unix échouent avec "... not found", lorsqu'elles sont exécutées via Java avec JSch, même avec setPty activé
  • Les commandes exécutées à l'aide de JSch se comportent différemment de celles du terminal SSH (contourne le message d'invite de confirmation de "oui /" non ")
  • JSch: Y a-t-il un moyen d'exposer les variables d'environnement de l'utilisateur au canal "exec"?
  • La commande (.4gl) exécutée avec SSH.NET SshClient.RunCommand échoue avec "Aucun fichier ou répertoire de ce type"

J'ai un morceau de code qui se connecte à un serveur Unix et exécute des commandes.

J'ai essayé avec des commandes simples et elles fonctionnent bien.

Je suis capable de me connecter et d’obtenir le résultat des commandes.

J'ai besoin d'exécuter un graphique Ab-initio via Java.

J'utilise la commande air sandbox run graph pour cela.

Il fonctionne bien lorsque je me connecte à l'aide du client SSH et que j'exécute la commande. Je suis capable d'exécuter le graphique. Cependant, lorsque j'essaie d'exécuter la commande via Java, l'erreur "air introuvable" est générée.

Existe-t-il une limite quant au type de commandes Unix prises en charge par JSch?

Avez-vous une idée de la raison pour laquelle je ne parviens pas à exécuter la commande avec mon code Java?

Voici le code:

public static void connect(){
    try{
      JSch jsch=new JSch();  

      String host="*****";
      String user="*****";
      String config =
                "Host foo\n"+
                "  User "+user+"\n"+
                "  Hostname "+host+"\n";

      ConfigRepository configRepository =
            com.jcraft.jsch.OpenSSHConfig.parse(config);

      jsch.setConfigRepository(configRepository);
      Session session=jsch.getSession("foo");

      String passwd ="*****";
      session.setPassword(passwd);
      UserInfo ui = new MyUserInfo(){

          public boolean promptYesNo(String message){

            int foo = 0;
            return foo==0;
          }
      };
      session.setUserInfo(ui);
      session.connect();

      String command="air sandbox run <graph-path>";

      Channel channel=session.openChannel("exec");
      ((ChannelExec)channel).setCommand(command);

      channel.setInputStream(null);

      ((ChannelExec)channel).setErrStream(System.err);

      InputStream in=channel.getInputStream();

      channel.connect();

      byte[] tmp=new byte[1024];
      while(true){
        while(in.available()>0){
          int i=in.read(tmp, 0, 1024);
          if(i<0)break;
          page_message=new String(tmp, 0, i);
          System.out.print(page_message);
        }
        if(channel.isClosed()){
          if(in.available()>0) continue; 
          System.out.println("exit-status: "+channel.getExitStatus());
          break;
        }
        try{Thread.sleep(1000);}catch(Exception ee){}
      }

      channel.disconnect();
      session.disconnect();
    }
    catch(Exception e){
      System.out.println(e);
    }
}

public static void main(String arg[]){
    connect();
}

public String return_message(){
      String ret_message=page_message;
      return ret_message;
}

public static abstract class MyUserInfo
    implements UserInfo, UIKeyboardInteractive{
    public String getPassword(){ return null; }
    public boolean promptYesNo(String str){ return false; }
    public String getPassphrase(){ return null; }
    public boolean promptPassphrase(String message){ return false; }
    public boolean promptPassword(String message){ return false; }
    public void showMessage(String message){ }
    public String[] promptKeyboardInteractive(String destination,
                        String name,
                        String instruction,
                        String[] prompt,
                        boolean[] echo){
        return null;
    }
}

Vous pouvez utiliser un fichier ~ / .ssh / environment pour définir vos variables AB_HOME et PATH.





jsch