Running Command on a Router Line By Line (JSCH API) - java

I have written a method in Java, which takes an ArrayList of Strings and tries to run the command on a CISCO router console one by one. And I am trying to print the output of each command on the console. I am using the Jsch API for it.
I am able to connect to the router just fine using SSH. But when I print the OutputStream to the console it just prints the same thing over and over again. No output of the commands I sent. I intentionally have a few incorrect commands in there so that the console prints the error, but I get no such thing.
Here is my method:
/**
* Deliver a config to the router line by line.
* #param configLines
* #throws DeviceExcpetion
*/
public void deliverConfig(List<String> configLines) throws DeviceExcpetion {
Channel channel = null;
JSch jSch = new JSch();
Session session = null;
try {
session = jSch.getSession(userid, ipAddress, port);
// Set the password.
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
// Finally make the connection.
session.connect();
channel = session.openChannel("shell");
InputStream inputStream = null;
ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
channel.setOutputStream(responseStream);
channel.connect();
for (String line : configLines) {
inputStream = new ByteArrayInputStream(line.getBytes(StandardCharsets.UTF_8));
channel.setInputStream(inputStream);
if (channel.isConnected()) {
Thread.sleep(1000);
}
String responseString = new String(responseStream.toByteArray());
System.out.println(responseString);
}
} catch (JSchException e) {
e.printStackTrace();
throw new DeviceExcpetion(e.getMessage());
} catch (InterruptedException e) {
e.printStackTrace();
throw new DeviceExcpetion(e.getMessage());
} finally {
if (session != null) {
session.disconnect();
}
if (channel != null) {
channel.disconnect();
}
}
}

Related

Hard Time Keeping JSCH Session Alive

I am trying to run a sequence of commands on a CSICO router using JSCH and SSH. But the problem I am having is after executing the first command, the second one just doesn't execute. The session seems to go down after running the first command. It throws this exception:
com.jcraft.jsch.JSchException: Packet corrupt
at com.jcraft.jsch.Session.start_discard(Session.java:1067)
at com.jcraft.jsch.Session.read(Session.java:937)
at com.jcraft.jsch.Session.connect(Session.java:309)
at com.jcraft.jsch.Session.connect(Session.java:183)
at com.att.ncaas.device.connection.ssh.SSHConnectionJSch.connect(SSHConnectionJSch.java:120)
The code look likes this:
public void connect () {
ChannelExec channelExec = null;
JSch jSch = new JSch();
Session session = null;
try {
session = jSch.getSession(userid, ipAddress, port);
// Set the password.
session.setPassword("XXXXXXXXX");
Properties properties = new Properties();
properties.put("StrictHostKeyChecking", "no");
// Set the Ciphers.
/*
* properties.put("cipher.s2c", "aes128-cbc"); properties.put("cipher.c2s",
* "aes128-cbc"); properties.put("CheckCiphers", "aes128-cbc");
*/
session.setConfig(properties);
// Finally make the connection.
session.connect();
channelExec = (ChannelExec) session.openChannel("exec");
// Command 1
channelExec.setCommand("show run");
ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
channelExec.setOutputStream(responseStream);
channelExec.connect();
while (channelExec.isConnected()) {
Thread.sleep(1000);
}
String responseString = new String(responseStream.toByteArray());
System.out.println("Show Run Output:\n");
System.out.println(responseString);
if (session.isConnected()) {
System.out.println("Wooooooooooooooooooohoooooooooooooooooooooooo!!!!");
} else {
session.connect();
}
// Command 2
channelExec.setCommand("show version");
channelExec.connect();
while (channelExec.isConnected()) {
Thread.sleep(1000);
}
responseString = new String(responseStream.toByteArray());
System.out.println("Show Version Output:\n");
System.out.println(responseString);
} catch (JSchException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null) {
session.disconnect();
}
if (channelExec != null) {
channelExec.disconnect();
}
}
}
When it comes for the second session.connect() inside the if block, it throws the error. The only other thing I noticed is the when I put the ciphers in, this part:
// Set the Ciphers.
properties.put("cipher.s2c", "aes128-cbc");
properties.put("cipher.c2s", "aes128-cbc");
properties.put("CheckCiphers", "aes128-cbc");
I get a different error on the same line. I get:
com.jcraft.jsch.JSchException: Session.connect: java.io.IOException: End of IO Stream Read
at com.jcraft.jsch.Session.connect(Session.java:565)
at com.jcraft.jsch.Session.connect(Session.java:183)
Any pointers on how to keep the session alive between two ChannelExec execute would really helpful. Thanks.
First, you cannot reuse the "exec" channel this way. You have to open a new channel for the new command.
And note that Cisco is known not to support multiple commands in one "exec" channel, even if specified together upfront:
Error passing multiple commands to Cisco CLI via plink
I would not be surprised if it did not support multiple "exec" channels in one connection either.
Did you test with an SSH client, if it is even possible, to do what you are trying to implement?

Why does reading from a shell channel output in JSch never end with -1?

I created an object called Obj which sends messages over a Secure Shell channel. I can send characters in UTF-8, which means that the output stream must handle multi-byte characters. That is why I decided to use a buffered output stream writer. That is not relevant, so the code only references that part of the code with a comment.
I'd like the input stream to also handle multibyte characters. I know that the read() function of the InputStreamReader will return integers that correspond to UTF-16 code points or -1. My current implementation loops and tests for -1. It loops endlessly. Why?
Here is my source code:
public class Obj {
public String sendMessage(char[] message) {
final int CONNECTION_TIMEOUT_MILLISECONDS = 300;
final int IN_BUFFER_SIZE = 2048;
int codePoint;
StringBuilder sbResponse = new StringBuilder();
try {
ChannelShell channel = SshChannelFactory.getChannel(this);
if (channel == null) {
System.out.println("Unable to acquire channel for object \"{}\"", this);
throw new RuntimeException();
}
channel.connect(CONNECTION_TIMEOUT_MILLISECONDS);
System.out.println("Successfully opened channel to \"{}\"", channel.getHost());
}
/**
* Write some stuff in this try block.
*/
//try {
//} catch
/**
* Read the response in this try block.
*/
char[] buffer = new char[IN_BUFFER_SIZE];
int bytesReadOffset = 0;
try {
BufferedReader fromServerStream = new BufferedReader(new InputStreamReader(channel.getInputStream(), Charset.forName("UTF-8")), IN_BUFFER_SIZE);
while ((codePoint = fromServerStream.read()) != -1) {
sbResponse.append((char) codePoint);
} catch (IOException e) {
e.printStackTrace();
}
return sbResponse.toString();
}
public class SshChannelFactory {
public static ChannelShell getChannel(Obj obj) {
return createSshChannel(obj);
}
private static Session createSshSession(Obj obj) {
final JSch jsch = new JSch();
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
try {
Session session = jsch.getSession(obj.getUser(), obj.getHost(), obj.getPort());
session.connect();
return session;
} catch (JschException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
private static ChannelShell createSshChannel() {
Session session = SSHSessionFactory.createSshSession(Obj obj)
try {
ChannelShell channel = (ChannelShell) session.openChannel("shell");
channel.setPty(true);
channel.setInputStream(null);
channel.setOutputStream(null);
return channel;
} catch (JSchException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
The "shell" channel opens a shell.
We do not know what your code actually does. But I'd assume that you send some command to the shell to be executed and then you try to read the command output. And you probably expect to get -1 once the command output ends. You won't.
The shell output stream ends, only when the shell ends. And for that you need to send some command like exit.
In general, you should not use the "shell" channel. It's intended for implementing an interactive shell session (like if you are implementing your own SSH terminal). That's something you rarely do.
To automate a command execution, use the "exec" channel.
See also What is the difference between the 'shell' channel and the 'exec' channel in JSch.

Sending Jsch commands

Beating my head against a wall here.
I am trying in the constructor to establish a link and log on. Then in the begin method to execute a java application on the remote computer. Finally in terminate, to kill the java process.
No exceptions show up, the command just doesn't execute. I can see the user has logged in if I go to the remote terminal and run a last. The user has only a login time of 0 though. I can also get an error if I change the password to the wrong password.
But the remote java app isn't running. Remote app runs fine when I log in directly from that terminal or ssh in and run it from the command line.
Ideas? Thanks in advance.
//Constants for the login information
String HOST="<HOSTNAME>";
String USER="<userid>";
String PASSWORD="<password>";
//Constants for command strings
String START_COMMAND="java -Djava.library.path=/usr/local/share/OpenCV/java -jar <filename>";
String TERMINATE_COMMAND="killall java";
Channel channel;
Session session;
InputStream in;
public VisionProcessing(){
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
JSch jsch = new JSch();
try {
System.out.println("Trying login");
session = jsch.getSession(USER, HOST, 22);
session.setPassword(PASSWORD);
session.setConfig(config); //XXX No idea what this does
session.connect();
channel=session.openChannel("exec");
((ChannelExec)channel).setPty(true);
channel.connect();//This is important
if (channel.isConnected()){
System.out.println("Connected");
} else {
System.out.println("Not Connected");
}
} catch (JSchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Exception logging in");
}
}
public boolean beginTargeting() {
try {
StringBuilder outputBuffer = new StringBuilder();
Channel channel = session.openChannel("exec");
InputStream commandOutput = channel.getInputStream();
int readByte = commandOutput.read();
while(readByte != 0xffffffff)
{
outputBuffer.append((char)readByte);
readByte = commandOutput.read();
}
System.out.println("Begin");
if (channel.isConnected()){
System.out.println("Connected");
((ChannelExec)channel).setCommand(START_COMMAND);
} else {
System.out.println("Not Connected");
}
channel.connect();//This is important
channel.disconnect();
}catch(IOException ioX)
{
System.out.println(ioX);
}
catch(JSchException jschX)
{
System.out.println(jschX);
}
return true;
}
public boolean terminateTargeting() {
try {
System.out.println("Terminate");
channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(TERMINATE_COMMAND);
channel.connect();//This is important
System.out.println("Terminating");
channel.setInputStream(null);
channel.disconnect();
session.disconnect();
System.out.println("DONE");
}catch(Exception ee){
System.out.println(ee);
}
return true;
}

Jsch java ssh client is not getting disconnected after command gets executed

I am using java ssh client (http://www.jcraft.com/jsch/) to connect to remote machine and execute the command.
The code is working fine till i connect to remote machine and execute the command. however, the issue is , the channel and session are not getting disconnected even after command executed successfully.
I have called session.disconnect and channel.disconnect as well but still the issue.
Here is my code:
JSch jsch = new JSch();
String host = null;
host = "192.168.102.211";
String privateKey = "C:\\test\\key";
String cmd = "a";
String command = "b";
jsch.addIdentity(privateKey);
Session session = jsch.getSession("user1", host, 22);
Channel channel = session.openChannel("shell");
UserInfo ui = new MyUserInfo() {
public boolean promptYesNo(String message) {
return true;
}
};
session.setUserInfo(ui);
session.connect(30000);
OutputStream ops = channel.getOutputStream();
PrintStream ps = new PrintStream(ops, true);
channel.connect();
ps.println(cmd);
ps.println(command);
ps.close();
InputStream in = channel.getInputStream();
byte[] bt = new byte[1024];
while (in.available() > 0) {
// int i = in.read(bt, 0, 1024);
for (int i = in.read(); i >=0; i--)
{
String str = new String(bt, 0, i);
System.out.print(str);
}
break;
}
if (channel != null) {
channel.disconnect();
session.disconnect();
System.out.println(channel.isConnected());
}
}
Please suggest
Update your question with a relevant code.
just a hint, you should do something like.
} finally {
if (channel != null) {
Session session = channel.getSession();
channel.disconnect();
session.disconnect();
System.out.println(channel.isConnected());
}
}
I have similar error I change my code to that
first I have declare session and channel
static Session session = null;
static Channel channel = null;
And this the connation code
public static OutputStream puttyConnection(String user, String hostName, String password)
throws JSchException, IOException {
session = new JSch().getSession(user, hostName, 22);
session.setPassword(password);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
channel = session.openChannel("shell");
OutputStream ops = channel.getOutputStream();
channel.connect();
return ops;
}
and in the finish of my running code I use to disconnect like that
if (channel != null) {
channel.disconnect();
session.disconnect();
System.out.println(channel.isConnected());
}
I encountered a similar problem, realizing that the channel could only be disconnected if it was closed. So I used the while loop to check if the channel is closed and then I was able to disconnect the channel without any problem.
while (true){
if(channel.isClosed()){
channel.disconnect();
break;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

Copy a file on remote server from one directory to other using Jsch

I am trying to copy a file on server from one directory to another one using Jsch. I am using SFTP protocol put and get methods to accomplish this task. I am doing this way as I dont have shell access to the server. Below is my code sample and the exception that I am getting. Can someone please let me know how to resolve it.
OutputStream outputStream = null;
InputStream inputStream = null;
try
{
JSch jsch = new JSch();
session = jsch.getSession(USER,HOST,PORT);
session.setPassword(PASS);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
config.put("PreferredAuthentications", "password");
session.setConfig(config);
session.connect();
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp)channel;
inputStream = channelSftp.get(fromFilename);
channelSftp.put(inputStream,toFilename);
} catch(Exception e){
e.printStackTrace();
} finally {
if(inputStream != null)
inputStream.close();
if(outputStream != null)
outputStream.close();
channelSftp.exit();
channel.disconnect();
session.disconnect();
}
Here is the exception
4: java.io.IOException: error: 4: RequestQueue: unknown request id 12
at com.jcraft.jsch.ChannelSftp._put(ChannelSftp.java:689)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:540)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:492)
You have to do the get() operation in a one channel and put() operation in another channel. That works. Here is my code.
public void cp (Session session, String source, String target) throws Exception {
log.info("COMMAND: cp " + source + " " + target);
if (!session.isConnected()) {
log.error("Session is not connected");
throw new Exception("Session is not connected...");
}
Channel upChannel = null;
Channel downChannel = null;
ChannelSftp uploadChannel = null;
ChannelSftp downloadChannel = null;
try {
upChannel = session.openChannel("sftp");
downChannel = session.openChannel("sftp");
upChannel.connect();
downChannel.connect();
uploadChannel = (ChannelSftp) upChannel;
downloadChannel = (ChannelSftp) downChannel;
FileProgressMonitor monitor = new FileProgressMonitor();
InputStream inputStream = uploadChannel.get(source);
downloadChannel.put(inputStream, target, monitor);
} catch (JSchException e) {
log.error("Auth failure", e);
throw new Exception(e);
} finally {
if (upChannel == null || downChannel == null) {
System.out.println("Channel is null ...");
}else if (uploadChannel != null && !uploadChannel.isClosed()){
uploadChannel.exit();
downloadChannel.exit();
uploadChannel.disconnect();
downloadChannel.disconnect();
}else if (!upChannel.isClosed()) {
upChannel.disconnect();
downChannel.disconnect();
}
session.disconnect();
}
}

Categories

Resources