2016-10-13 12 views
2

У меня есть фрагмент кода, который соединяется с сервером Unix и выполняет команды.Определенные команды Unix с «... не найдены» при выполнении через Java с использованием JSch

Я пытался с помощью простых команд, и они отлично работают.

Я могу войти и получить выходные данные команд.

Мне нужно запустить график Ab-initio через Java.

Для этого используется команда air sandbox run graph.

Он работает нормально, когда я использую SSH-клиент и выполняю команду. Я могу запустить график. Однако, когда я пытаюсь запустить команду через Java, она дает мне Ошибка «воздух не найден».

Есть ли какой-либо предел в отношении каких команд Unix поддерживает JSch?

Любая идея, почему я не могу запустить команду через свой Java-код?

Вот код:

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; 
    } 
} 

ответ

4

"Exec" канал в JSch (по праву) не выделяет псевдо терминал (PTY) для сеанса. Как следствие, используется другой набор сценариев запуска (может быть). И/или разные ветви в сценариях берутся на основе отсутствия/наличия переменной окружения TERM. Таким образом, среда может отличаться от интерактивной сессии, которую вы используете с вашим SSH-клиентом.

Таким образом, в вашем случае PATH, вероятно, установлен по-разному; и, следовательно, исполняемый файл air не найден.

Чтобы убедиться, что это основная причина, отключите распределение псевдотерминалов в своем SSH-клиенте. Например, в PuTTY это Connection> SSH> TTY> Не выделяйте псевдотерминал. Затем перейдите к Connection> SSH> Удаленная команда и введите команду air .... Проверьте Сессия> Закройте окно при выходе> Никогда и откройте сеанс. Вы должны получить то же самое «воздух не найден» ошибка.


способы исправить это, в порядке предпочтения:

  1. Фикс команды не полагаться на конкретную среду. Используйте полный путь до air в команде.

  2. Исправьте сценарии запуска, чтобы установить PATH то же самое для интерактивных и неинтерактивных сессий.

  3. Если команда сама полагается на определенную настройку среды, и вы не можете исправить сценарии запуска, вы можете изменить среду в самой команде. Синтаксис для этого зависит от удаленной системы и/или оболочки.В общих * NIX систем, это работает:

    String command="PATH=\"$PATH;/path/to/air\" && air sandbox run <graph-path>"; 
    
  4. Другой (не рекомендуется) подход, чтобы заставить псевдо терминала распределения для «ехес» канала с использованием .setPty метод:

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

    Использование псевдотерминал для автоматизации выполнения команды может привести к неприятным побочным эффектам. Смотрите, например Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?


В течение подобных вопросов см

+0

Я попытался отключить выделение псевдотерминалов в моем клиенте PuTTY, а затем выполнить команду. Команда выполнена успешно. – karansabhani

+0

Я также пытался принудительно назначить псевдотерминал для канала «exec», и команда все еще не выполнялась. Как исправить мои сценарии запуска, чтобы установить переменную PATH для интерактивных и неинтерактивных сеансов? – karansabhani

+0

Вы использовали поле «Удаленная команда» для ввода команды «воздух ...»? Что делает 'plink -ssh user @ host air sandbox run graph' do? –

1

вы могли бы попытаться выяснить Whe re "air" проживает с

whereis air 

, а затем использовать этот результат.

что-то вроде

/usr/bin/air sandbox run graph 
1

Вы можете использовать файл ~/.ssh/окружающей среды, чтобы установить ваши AB_HOME и PATH переменных.