当使用JSch通过Java执行时,某些Unix命令失败并显示“... not found”

问题描述 投票:2回答:3

我有一段连接到Unix服务器并执行命令的代码。

我一直在尝试简单的命令,他们工作正常。

我能够登录并获得命令的输出。

我需要通过Java运行Ab-initio图。

我正在使用air sandbox run graph命令。

当我使用SSH客户端登录并运行命令时,它运行正常。我能够运行图表。但是,当我尝试通过Java运行命令时,它会给我一个“未找到空气”的错误。

对JSch支持的Unix命令有什么限制吗?

知道为什么我无法通过我的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;
    }
}
java shell unix ssh jsch
3个回答
6
投票

JSch中的“exec”通道(正确地)不为会话分配伪终端(PTY)。因此,可能(可能)采购了一组不同的启动脚本(特别是对于非交互式会话,.bash_profile不是来源的)。和/或脚本中的不同分支基于TERM环境变量的不存在/存在而被采用。所以环境可能与交互式会话不同,您可以使用SSH客户端。

所以,在你的情况下,PATH可能设置不同;因此无法找到air可执行文件。

要验证这是根本原因,请在SSH客户端中禁用伪终端分配。例如,在PuTTY中,它的连接> SSH> TTY>不分配伪终端。然后,转到Connection> SSH> Remote命令并输入air ...命令。在退出时检查会话>关闭窗口>从不打开会话。您应该得到相同的“未找到空气”错误。


按优先顺序解决此问题的方法:

  1. 修复命令不依赖于特定环境。在命令中使用air的完整路径。例如。: /bin/air sandbox run <graph-path> 如果您不知道完整路径,则在常见的* nix系统上,您可以在交互式SSH会话中使用which air命令。
  2. 修复启动脚本,以便为交互式和非交互式会话设置PATH
  3. 尝试通过登录shell显式运行脚本(使用带有常见* nix shell的--login开关): bash --login -c "air sandbox run sandbox run <graph-path>"
  4. 如果命令本身依赖于特定的环境设置而无法修复启动脚本,则可以在命令本身中更改环境。该语法取决于远程系统和/或shell。在常见的* nix系统中,这有效: String command="PATH=\"$PATH;/path/to/air\" && air sandbox run <graph-path>";
  5. 另一种(不推荐)方法是使用.setPty方法强制“exec”通道的伪终端分配: 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?

对于类似的问题,请参阅


1
投票

你可以尝试找出“空气”所在的位置

whereis air

然后使用这个结果。

就像是

/usr/bin/air sandbox run graph

1
投票

您可以使用〜/ .ssh / environment文件来设置AB_HOME和PATH变量。

© www.soinside.com 2019 - 2024. All rights reserved.