I am trying to run a command on a remote Linux box from Java using JSch (SSH) API. The value of exitStatus is -1 i.e.
int exitStatus = channelExec.getExitStatus()
What is the possible reason to get a negative value?
Note the documentation on getExitStatus().
The exit status will be -1 until the channel is closed.
API Description
Here is my code. It works fine.
public static Result sendCommand(String ip, Integer port, String userName, String password, String cmd) {
Session session = null;
ChannelExec channel = null;
Result result = null;
try {
JSch jsch = new JSch();
JSch.setConfig("StrictHostKeyChecking", "no");
session = jsch.getSession(userName, ip, port);
session.setPassword(password);
session.connect();
channel = (ChannelExec)session.openChannel("exec");
InputStream in = channel.getInputStream();
channel.setErrStream(System.err);
channel.setCommand(cmd);
channel.connect();
StringBuilder message = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = reader.readLine()) != null)
{
message.append(line).append("\n");
}
channel.disconnect();
while (!channel.isClosed()) {
}
result = new Result(channel.getExitStatus(),message.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null) {
try {
session.disconnect();
} catch (Exception e) {
}
}
}
return result;
}
'-1' means that the exit status code has not been received yet from the remote sshd.
channelName.getExitStatus()
it will retrieve the exit status of the remote command corresponding to your channel. If the command is not yet terminated (or this channel type has no command), it will return the status as -1.
For more got to jsch documentation.
Related
I have a system where it connects to a SMS Gateway.I use sqlite3 to connect to the database of the Gateway. The system connects to the Gateway and retrieves messages then saves it to an Oracle database. My problem is that the format of the messages disappears once I set the values of the message to an object.
Is there any way to encode the message in the query?
I've tried doing this:
SELECT URLENCODE(*) FROM SMSRECV;
I know that this is not a proper function, but I still tried because I really can't find a way
Connecting to the gateway via ssh
private String getSmsDump() {
StringBuilder sb = new StringBuilder();
try {
String command = "sqlite3 /persistent/var/lib/asterisk/db/MyPBX.sqlite \".read /persistent/script/cwms/smsrecv_html.sqlc\"";
String host = this.sshHost;
String user = this.sshUser;
String password = this.sshPassword;
int port = this.sshPort;
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
session.connect();
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
InputStream input = channel.getInputStream();
channel.connect();
try {
InputStreamReader inputReader = new InputStreamReader(input);
BufferedReader bufferedReader = new BufferedReader(inputReader);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
inputReader.close();
} catch (Exception ex) {
LOGGER.error("BUFFERED READER ERROR: "+ex);
}
channel.disconnect();
session.disconnect();
} catch (JSchException | IOException ex) {
LOGGER.error("SSH CONNECTION ERROR: "+ex);
}
return sb.toString();
} // end getSmsHtmlDump()
Setting the values to an object:
public List<SmsMessage> getSmsMessages() {
List<SmsMessage> result = new ArrayList();
String smsDump = getSmsDump();
String received = "RECEIVED";
String status = "1";
if (null != smsDump) {
Document messageDump = Jsoup.parse("<html><head></head><body><table>" + smsDump + "</table></body></html>");
Elements rows = messageDump.getElementsByTag("tr");
String hasRead = "0"; //no
// Lambda expression for iterating row elements
rows.stream().map((Element row) -> {
SmsMessage message = new SmsMessage();
Elements cols = row.getElementsByTag("td");
message.setMessageId(cols.get(0).text()); // Message ID
message.setSender(cols.get(1).text()); // Sender
message.setSmsc(cols.get(2).text()); // SMSC
message.setPortId(cols.get(3).text()); // Port ID
message.setContent(cols.get(4).text());
LOGGER.debug(cols.get(4).text());// Content
message.setReceiveTime(cols.get(5).text()); // Receive Time
message.setHasRead(hasRead); // Has Read
message.setTypeOfMessage(received);
message.setMessageStatus(status);
return message;
}).forEachOrdered((message) -> {
result.add(message);
//LOGGER.debug(message.toString());
});
}
return result;
} // end getSmsMessages()
Content of the smsrecv_html.sqlc file:
.mode html
SELECT * FROM SMSRECV;
I just want to set the values to the object without removing the format
Hope you could help me.
Thank you!
This question already has answers here:
Certain Unix commands fail with "... not found", when executed through Java using JSch
(3 answers)
Closed 3 years ago.
I am trying to develop a small application that allows me to send certain commands by SSH to a remote server. If I try it from the Linux terminal or from the Windows Command Prompt it works without problems, but when I do it from my Java application it always responds with a status code of 255.
I have disabled the firewall and I have changed the port where I have listening SSH on the server to 22, because I use another, but nothing works. It does not throw me exceptions or anything and if it connects without problems. Any ideas?
I have tried with the sshj and JSch libraries and with both I have the same problem.
ForwardAgent is turn off
sshj example
private void sshj() throws Exception {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier((s, i, publicKey) -> true);
ssh.connect("host", 22);
Session session = null;
try {
ssh.authPassword("username", "password");
session = ssh.startSession();
Session.Command cmd = session.exec("command");
System.out.println(IOUtils.readFully(cmd.getInputStream()).toString());
cmd.join(5, TimeUnit.SECONDS);
System.out.println("Exit status: " + cmd.getExitStatus());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
ssh.disconnect();
}
}
JSch example
private static void jsch() throws Exception {
JSch js = new JSch();
Session s = js.getSession("username", "host", 22);
s.setPassword("password");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
s.setConfig(config);
s.connect();
Channel c = s.openChannel("exec");
ChannelExec ce = (ChannelExec) c;
ce.setCommand("command");
ce.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(ce.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
ce.disconnect();
s.disconnect();
System.out.println("Exit status: " + ce.getExitStatus());
}
change to code so that you get the inputStream before doing connect
InputStream in = ce.getInputStream();
ce.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
Also, the getSession is wrong as it should be
public Session getSession(String username,
String host,
int port)
edit
The below code works for me
JSch js = new JSch();
Session s = js.getSession("username", "127.0.0.1", 22);
s.setPassword("password");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
s.setConfig(config);
s.connect();
Channel c = s.openChannel("exec");
ChannelExec ce = (ChannelExec) c;
ce.setCommand("uptime");
InputStream in = ce.getInputStream();
ce.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
ce.disconnect();
s.disconnect();
System.out.println("Exit status: " + ce.getExitStatus());
output
10:26:08 up 149 days, 58 min, 3 users, load average: 0.61, 0.68, 0.68
Exit status: 0
I'm developing java program to connect with windows server over ssh. For this I used jcraft on java. And the ssh server is copSSH. The implementation throws
Error: com.jcraft.jsch.JSchException: Algorithm negotiation fail
error on java. At the same time it shows
fatal: Unable to negotiate with 192.168.28.111: no matching cipher
found. Their offer: aes128-cbc,3des-cbc,blowfish-cbc [preauth]
on CopSSH.
Java code block
public void sshExecPassword(String host, String USERNAME, String PASSWORD, String command) {
App objApp = new App();
int port = 22;
try {
/**
* Create a new Jsch object This object will execute shell commands
* or scripts on server
*/
JSch jsch = new JSch();
/*
* Open a new session, with your username, host and port Set the
* password and call connect. session.connect() opens a new
* connection to remote SSH server. Once the connection is
* established, you can initiate a new channel. this channel is
* needed to connect to remotely execution program
*/
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
Session session = jsch.getSession(USERNAME, host, port);
session.setConfig(config);
session.setPassword(PASSWORD);
session.connect();
// create the excution channel over the session
ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
// Gets an InputStream for this channel. All data arriving in as
// messages from the remote side can be read from this stream.
InputStream in = channelExec.getInputStream();
// Set the command that you want to execute
// In our case its the remote shell script
String str = command;
channelExec.setCommand(str);
channelExec.connect();
// Read the output from the input stream we set above
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// retrieve the exit status of the remote command corresponding to
// this channel
int exitStatus = channelExec.getExitStatus();
// Safely disconnect channel and disconnect session. If not done
// then it may cause resource leak
channelExec.disconnect();
session.disconnect();
if (exitStatus < 0) {
System.out.println("Done, but exit status not set! " + exitStatus);
objApp.writeLogs("120","Done, but exit status not set! ");
} else if (exitStatus > 0) {
System.out.println("Done, but with error!");
objApp.writeLogs("120","Done, but with error!");
} else {
System.out.println("Done!");
objApp.writeLogs("121","SSH connection successful");
}
} catch (Exception e) {
System.err.println("Error: " + e);
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
e.printStackTrace(pw);
objApp.writeLogs("120", sw.getBuffer().toString());
}
}
And the CopSSH host following versions
OpenSSH_7.1p2, OpenSSL 1.0.2e 3 Dec 2015
Can any one suggest a fix for it?
That happens due to lacking support for legacy ciphers in more recent releases of OpenSSH. Check this Copssh FAQ for a solution. Background information can also be found here.
Latest jcraft jar fix the issue
I have a text file on server with a size of 200 mb.I want reduce the file content using command (grep keyword1 filename.txt|grep -v keyword2) and then read that file in java using Jsch connection.
I solved the issue by below code:-
JSch jsch = new JSch();
Session session = null;
try {
String command="grep 'keyword1' filename.txt|grep -v 'keyword2'";
session = jsch.getSession(userid, servername, serverport);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");
session.connect();
Channel channel = session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
channel.connect();
InputStream commandOutput = channel.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(commandOutput));
String line="";
while ((line = br.readLine()) != null)
{
System.out.println(line);
}
br.close();
channel.disconnect();
session.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
I need to execute some remote commands on unix box using java. For that I have used jsch but the issue is that I need to collect the output of last command.
i wrote the below piece of code:
public static String run(String hostname, String hostPort, String username, String password, String[] commands) throws JSchException, IOException
{
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, 22);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
// System.out.println("Connected");
ChannelExec channel = (ChannelExec) session.openChannel("exec");
BufferedReader in = new BufferedReader(new InputStreamReader(channel.getInputStream()));
StringBuffer sb = new StringBuffer();
for (String s : commands)
{
sb.append(s + ';');
}
String command = sb.toString();
channel.setCommand(command);
channel.connect();
String msg = null;
//String output = "";
StringBuffer output = new StringBuffer();
while ((msg = in.readLine()) != null)
{
//output = output + msg;
output.append(msg);
}
channel.disconnect();
session.disconnect();
// System.out.println("DONE");
return output.toString();
}
In the above code, I am collecting all the command result but i need to collect only result of last command fired.
Please provide your inputs.