【问题标题】:Shell ping command with source option is failing when executed using JSch setCommand使用 JSch setCommand 执行带有源选项的 Shell ping 命令失败
【发布时间】:2016-06-23 01:15:13
【问题描述】:

我正在测试短 ping 测试程序。如果我将简单的 ping 命令 "ping y.y.y.y -c 5 -s 500 " 设置为 setCommand() 函数,它会按设计工作。但是如果我添加额外的 ping 选项,"ping source x.x.x.x host y.y.y.y -c 5 -s 500",我得到了

ping: 未知主机来源

回消息。如果我从 x 终端手动执行这两个命令,这两个命令都可以正常工作。

我需要让程序从不同的源接口 IP ping 通。使用JSchsetCommand的两个命令有什么区别?

  1. ping y.y.y.y -c 5 -s 500(工作中)
  2. ping source x.x.x.x host y.y.y.y -c 5 -s 500(不工作)

代码:

public static void main(String[] arg){
try{
  JSch jsch=new JSch();  

  String host=null;
  if(arg.length>0){
    host=arg[0];
  }
  else{
    host=JOptionPane.showInputDialog("Enter username@hostname",
                                     System.getProperty("user.name")+
                                     "@localhost"); 
  }
  String user=host.substring(0, host.indexOf('@'));
  host=host.substring(host.indexOf('@')+1);

  Session session=jsch.getSession(user, host, 22);

  UserInfo ui=new MyUserInfo();
  session.setUserInfo(ui);
  session.connect();

  // this command works
  // String command = "ping 20.5.1.15 -c " + count + " -s " + size;

  // this command not working
  String command = "ping source 20.5.1.10 host 20.5.1.15 -c " + count + " -s
  " + size;

  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;
      System.out.print(new String(tmp, 0, i));
    }
    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);
}

【问题讨论】:

    标签: java shell ssh jsch


    【解决方案1】:

    你的ping source x.x.x.x host y.y.y.y 语法对我来说似乎很奇怪。但我相信你它可以在终端中工作。


    ping 命令可能依赖于某些环境变量或其他配置来解析源地址。

    JSch 中的“exec”通道(正确地)没有为会话分配伪终端 (PTY)。因此,(可能)获取了一组不同的启动脚本。和/或脚本中的不同分支基于TERM 环境变量的缺席/存在而被采用。因此,环境可能与您在 SSH 客户端中使用的交互式会话不同。

    如果这破坏了ping 命令,这显然是服务器端的错误配置,而不是 JSch 错误。 ping 不是交互式命令,因此即使在非交互式会话上也应该可以工作。您应该找出破坏ping 的原因并相应地修复您的启动脚本。

    要验证这是根本原因,请在 SSH 客户端中禁用伪终端分配。例如在 PuTTY 中,它是 Connection > SSH > TTY > Don't allocate a pseudo terminal。然后转到 Connection > SSH > Remote command 并使用ping source ... 命令。检查会话>退出时关闭窗口>从不并打开会话。


    另一种(不推荐)方法是使用.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?


    这是这个常见问题的一个特例:
    Certain Unix commands fail with "... not found", when executed through Java using JSch

    【讨论】:

    • 谢谢。现在我明白了原因。我试图通过选中“不分配伪终端”来验证 Putty 连接,但建立连接失败。而“.setPty”选项并没有解决这个问题。现在我被困住了。如何使 ping 命令(来自各种源接口)起作用?
    • 建立连接失败 - 它究竟是如何失败的?
    • 挂了。我没有看到提示。我能够看到登录提示,但是在我输入登录 ID 和密码后,终端被挂起。
    • 嗯,所以连接成功了,对吧?如果您需要我们的帮助,请确保您准确无误。
    • 是的,连接已建立。但是我无法验证 ping 命令,因为终端在输入密码后卡住了。
    猜你喜欢
    • 1970-01-01
    • 2011-08-15
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    • 2019-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多