Shell ping command with source option is failing w

2019-06-07 02:33发布

I'm testing short ping test program. If I set simple ping command, "ping y.y.y.y -c 5 -s 500 " into setCommand() function, it works as designed. But if I add addition ping options, "ping source x.x.x.x host y.y.y.y -c 5 -s 500", I got

ping: unknown host source

message back. If I manually execute both commands from the x-terminal, the both commands works fine.

I need to make the program to ping from different source interface IPs. What is the difference between two commands using JSch setCommand?

  1. ping y.y.y.y -c 5 -s 500 (working)
  2. ping source x.x.x.x host y.y.y.y -c 5 -s 500 (not working)

Code:

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

1条回答
Ridiculous、
2楼-- · 2019-06-07 03:09

Your ping source x.x.x.x host y.y.y.y syntax seems strange to me. But I will trust you that it works in the terminal.


The ping command probably depends on some environment variable or other configuration to resolve the source address.

The "exec" channel in the JSch (rightfully) does not allocate a pseudo terminal (PTY) for the session. As a consequence a different set of startup scripts is (might be) sourced. And/or different branches in the scripts are taken, based on absence/presence of the TERM environment variable. So the environment might differ from the interactive session you use with your SSH client.

If this breaks the ping command, it's clearly misconfiguration on the server-side, not JSch fault. The ping is not an interactive command, so it should work even on the non-interactive session. You should find out what is it that breaks the ping and fix your startup scripts accordingly.

To verify that this is the root cause, disable the pseudo terminal allocation in your SSH client. For example in PuTTY, it's Connection > SSH > TTY > Don't allocate a pseudo terminal. Then go to Connection > SSH > Remote command and ether your ping source ... command. Check Session > Close window on exit > Never and open the session.


Another (not recommended) approach is to force the pseudo terminal allocation for the "exec" channel using the .setPty method:

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

Using the pseudo terminal to automate a command execution can bring you nasty side effects. See for example 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?


This is a special case of this common problem:
Certain Unix commands fail with "... not found", when executed through Java using JSch

查看更多
登录 后发表回答