Skip to content
Advertisement

Executing multiple commands over SSH “exec” channel on firewall device with Java JSch does not work

I referred the question Multiple bash commands and implemented as below. I am connecting to a device for which first command should be configure then only I will get a prompt to execute all other commands. I don’t get output for any of the commands and the control does not return.

The following are the commands that work in terminal.

ssh uname@ip
configure # this command changes prompt and enable following commands
move shared pre-rulebase security rules TEST top 
commit
exit
exit

As asked for, if I do this instead, after entering password the control doesn’t return:

ssh user@host configure

The script

String[] commands = new String[]{
    "configure", "move shared pre-rulebase security rules TEST top", "commit", "exit"};

FileWriter fileOut = new FileWriter(outFileName, true);
java.util.Properties config = new java.util.Properties();

config.put("StrictHostKeyChecking", "no");
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, 22);
session.setPassword(password);
session.setConfig(config);
session.connect();
System.out.println("Connected");

System.out.println(commands[0]);
ChannelExec channel = (ChannelExec) session.openChannel("exec");
((ChannelExec) channel).setCommand(commands[0]);
channel.setInputStream(null);
((ChannelExec)channel).setErrStream(System.err);

InputStream in = channel.getInputStream();
outStream = channel.getOutputStream();
channel.connect();

Thread.sleep(1000);

for(int i=1;i<commands.length;i++) {
    System.out.println("Executing:"+commands[i]);
    outStream.write((commands[i]+"n").getBytes());
    outStream.flush();
}

byte[] tmp = new byte[1024];
while (true) {
    while (in.available() > 0) {
        int i = in.read(tmp, 0, 1024);
        if (i < 0)
            break;
        resultString = new String(tmp, 0, i);                   
        fileOut.write(resultString);
    }
    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();
outStream.close();
fileOut.close();

Advertisement

Answer

The “exec” channel on your device seems to be implemented incorrectly. So you cannot use your code with the “exec” channel. As you can “ssh” to the device, it seems that the “shell” channel is fully working. Try talking to your server administrator, to get the server fixed.

If fixing the server is not feasible, you will have to revert to using the “shell” channel, although it is generally not the correct way to implement command automation.
See What is the difference between the ‘shell’ channel and the ‘exec’ channel in JSch

JSch by default enables terminal emulation for the “shell” channel, what will bring lot of unwanted side effects (see Getting unwanted characters when reading command output from SSH server using JSch). You may need to disable that by calling setPty.

ChannelShell channel = (ChannelShell) session.openChannel("shell"); 

InputStream in = channel.getInputStream(); 
outStream = channel.getOutputStream(); 

channel.setPty(false);
channel.connect(); 

outStream.write('configuren'.getBytes());  
outStream.write('move shared pre-rulebase security rules TEST topn'.getBytes());
7 People found this is helpful
Advertisement