1

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);
}
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
John Lee
  • 11
  • 1

1 Answers1

0

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

Community
  • 1
  • 1
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • Thank you. now I understand the cause. I tried to verify Putty connection with "Don't allocate a pseudo terminal" checked, but establishing the connection was failed. And ".setPty" option didn't resolved the issue. Now I'm stuck. How do I make ping command (from various source interface) works? – John Lee Mar 09 '16 at 19:53
  • *establishing the connection was failed* - How did it fail exactly? – Martin Prikryl Mar 09 '16 at 19:55
  • It hung. I don't see a prompt. I was able to see login prompt, but after I typed in login ID, then Password, the terminal got hung. – John Lee Mar 09 '16 at 19:56
  • Well, so the connection succeeded, right? If you want our help, make sure you are exact. – Martin Prikryl Mar 09 '16 at 20:10
  • Yes the connection was made. But I wasn't able to verify the ping command because the terminal got stuck after typed in the password. – John Lee Mar 09 '16 at 20:29
  • Did you enter the `ping` command to the *Connection > SSH > Remote command*? – Martin Prikryl Mar 10 '16 at 06:46
  • Yes I received same answer. – John Lee Mar 10 '16 at 17:26
  • Yes I received same answer saying "ping: unknown host source." Since I couldn't get what I want with openChannel("exec"), I changed my code to use openChannel("shell") now, and it works good. Only disadvantage is that I have to make my code to send a next command based on result of a previous command. setCommnd was good for that purpose. – John Lee Mar 10 '16 at 17:33