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
?
ping y.y.y.y -c 5 -s 500
(working)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);
}
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. Theping
is not an interactive command, so it should work even on the non-interactive session. You should find out what is it that breaks theping
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: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