Jsch : Command Output unavailable - java

I am trying to use jsch to connect to a remote switch and run some command and extract the output.
I am able to connect to the switch using , however the command output is not available in the inputstream. Maybe i am not doing it the right way. Here's the code
session = jsch.getSession("user", "10.0.0.0", 22);
session.setPassword("somepwd");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
System.out.println("connected to remote host");
Channel channel = session.openChannel("shell");
OutputStream ops = channel.getOutputStream();
PrintStream ps = new PrintStream(ops);
channel.connect();
ps.println("show version");
ps.flush();
ps.close();
InputStream in=channel.getInputStream();
byte[] bt=new byte[1024];
while(in.available()>0)
{
int i=in.read(bt, 0, 1024);
if(i<0)
break;
String str=new String(bt, 0, i);
//displays the output of the command executed.
System.out.print(str);
}
channel.disconnect();
session.disconnect();
When i debug the inputStream.isAvailable() always returns zero suggesting that there is no output from the command.
TIA!

Please try the code below - tested and working
Channel channel = session.openChannel("shell");
OutputStream ops = channel.getOutputStream();
PrintStream ps = new PrintStream(ops);
channel.connect();
ps.println("pwd");
ps.println("exit");
ps.flush();
ps.close();
InputStream in = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
System.out.println("Opening...");
String jarOutput;
while ((jarOutput = reader.readLine()) != null)
System.out.println(jarOutput);
reader.close();
channel.disconnect();
Output -
Opening...
user#host:~> pwd
/home/user
user#host:~>
user#host:~> exit
logout

Related

How to run "show interfaces status" to Cisco/Alcatel switch via java (jsch if possible)

I need run show interfaces status to Cisco/Alcatel switch via java (jsch if possible)
I use SSH to access this swith. after I try
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
channel.setOutputStream(System.out);
InputStream in = channel.getInputStream();
channel.connect();
I try this (OK if I run manually command in console)
Channel channel = session.openChannel("shell");
channel.setInputStream(null);
channel.connect();
I need connect, send command and record the result of command. If I exec this manually the result is OK. I try my code in a virtual machine and the result is different to a physical switch.
You can try this :
Channel channel=null;
String result = null;
try
{
channel = session.openChannel("exec");
String Command = "show interfaces status"; // Command
//System.out.println("Command : "+Command);
((ChannelExec)channel).setCommand(Command);
InputStream in=channel.getInputStream();
byte[] tmp=new byte[1024];
channel.connect();
if(channel.isConnected())
{
//System.out.println("Channel connected");
}
while(true)
{ // geeting the result in this loop
while(in.available()>0)
{
int i=in.read(tmp, 0, 1024);
if(i<0)break;
result += new String(tmp, 0, i); // result
}
if(channel.isClosed())
{
break;
}
else
{
try{ Thread.sleep(1000); }catch(Exception ee){}
}
}
}
catch(JSchException e)
{
// your exception message
}

How to run Jsch multiple commands from shell-channel using String input instead of console

I am writing a program using JSch library, and have to open a shell channel and execute few commands that are stored in String.
I need to feed the input commands from String variable rather than console.
I have come across a post Jsch : Command Output unavailable
In code given, its working fine for commands like pwd,whoami etc, but its going for a hang when i am trying to do a sudo -u hiveuser -i.
Here is the code:
public static void main(String[] args) throws Exception
{
JSch jsch = new JSch();
String host = "my.host.server";
String user = "myLoginId";
String pswd = "myPASSword";
Session session=jsch.getSession(user,host, 22);
session.setPassword(pswd);
session.setConfig("StrictHostKeyChecking", "no");
session.setConfig("PreferredAuthentications","publickey,keyboard-interactive,password");
session.connect();
System.out.println("Connected");
Channel channel = session.openChannel("shell");
OutputStream ops = channel.getOutputStream();
PrintStream ps = new PrintStream(ops);
channel.connect();
ps.println("sudo -iu hiveuser");
ps.println(pswd);
ps.println("hive");
ps.println("desc table myHiveTable;");
ps.flush();
ps.close();
InputStream in = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
System.out.println("Opening...");
String jarOutput;
while ((jarOutput = reader.readLine()) != null)
System.out.println(jarOutput);
reader.close();
channel.disconnect();
session.disconnect();
}
You could try echoing in the password:
echo password | sudo -iu hiveuser --stdin

How i can read file from unix server after doing some grep operation using java(Jsch)

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();
}

Java code to run command on remote Linux with sesu access

I need java code that logs into linux box with my credentials, then do a sesu , and then execute a shell script. Permission to execute the shell script if for only sesu user, hence sesu-ing after login is critical. I used te following code which can help me execute a command with my credential scope, however, I need sesu login following my login. Please suggest a way.
I tried adding the sesu command in teh command list, but it prompts for a password. I want a way to pass the password as well and completly automate it.
import java.io.InputStream;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
public class SSHCommandExecutor {
/** * #param args */
public static void main(String[] args) {
String host = "xxxxxxx";
String user = "xxxxxxx";
String password = "xxxxxxx";
String command1 = "cd /test; ./test.sh";
try {
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");
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command1);
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()) {
System.out.println("exit-status: " + channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {}
}
channel.disconnect();
session.disconnect();
System.out.println("DONE");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Variant A: Using JSch all the way
This minimal script (test.sh) requests an input from stdin before putting out one line of data:
#!/bin/bash
echo -n "Is this a good question (y/n)? "
read answer
if echo "$answer" | grep -iq "^y" ;then
echo Yes
else
echo No
fi
So it should be equivalent to your call requesting a password to be given. Now have a look at this code on how to send data into that process
String command1 = "cd /home/jan; ./test.sh";
try {
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");
ChannelExec channel = (ChannelExec)session.openChannel("exec");
OutputStream o = channel.getOutputStream();
PrintWriter pw = new PrintWriter(o);
InputStream in = channel.getInputStream();
((ChannelExec) channel).setCommand(command1);
channel.connect();
// 1 - Reading the prompt to input password
byte[] buf = new byte[255];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
// 2 - Send (password) data and flush stream
pw.println("y");
pw.flush();
// 3 - Read result
BufferedReader br = new BufferedReader(new InputStreamReader(in));
System.out.println(br.readLine());
// 4 - Clean up
channel.disconnect();
session.disconnect();
Variant B: Shell magic
String command1 = "cd /test; echo 'password' | ./test.sh";
or
String command1 = "cd /test; ./test.sh <<< 'password'";
(of cause you'd need to specify correct password there)
To run remote script with root privileges even if login user does not have them see here:
https://askubuntu.com/questions/155791/how-do-i-sudo-a-command-in-a-script-without-being-asked-for-a-password

ssh through java, store error in variable

I am executing a rm command via ssh using the jsch library.
The command is being sent and executed correctly.
But when the file I want to delete is not found in the directory, I get an error message as follows:
No such file or directory
I want to store the error message in a variable and use it afterwards.
Currently this message is displayed when the following are executed:
((ChannelExec)channel).setErrStream(System.err);
InputStream in=channel.getInputStream();
channel.connect();
after the channel.connect() the message error mesg is displayed.
How can I store it in a variable let's say string and print it after completion?
Below is the main class.
String SSHHOST = "127.0.0.1";
int SSHPPORT = 22;
String SSHPUSER = "user";
String SSHPPASS = "pass";
StringBuilder result = new StringBuilder();
System.out.println("Connecting To Server "+SSHHOST);
JSch jsch = new JSch();
Session session=jsch.getSession(SSHPUSER, SSHHOST, 22);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(SSHPPASS);
session.connect();
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand("find /home/test/DC* -print -exec rm {} \\;|wc -l");
channel.setInputStream(null);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
((ChannelExec)channel).setErrStream(bos) ;
((ChannelExec)channel).setErrStream(System.err);
InputStream in=channel.getInputStream();
channel.connect();
String result2 = bos.toString();
System.out.println(result2);
byte[] tmp=new byte[1024];
while(true)
{
while(in.available()>0)
{
int i=in.read(tmp, 0, 1024);
if(i<0)break;
out=new String(tmp, 0, i);
}
if(channel.isClosed())
{
//System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try
{
Thread.sleep(1000);
}catch(Exception ee){}
}
channel.disconnect();
session.disconnect();
int status = channel.getExitStatus();
System.out.println(out.trim());
if (channel.getExitStatus() == 0)
{
System.out.println("Perso file purging process completed successfully.");
System.out.println("exit-status: "+channel.getExitStatus());
System.out.println("Number of perso files deleted : "+out);
}
else
{
System.out.println("Perso file purging process completed with errors.");
}
I am still unable to get the error message when the files are not found in the directory with the above code.
This is a bit of a guess from me but .....
You seem to be setting the error stream of your channel object to the System.err of your application - unless you have reconfigured the System.err of your application to point to somewhere else, that will be the console.
What arguments does setErrStream take? If it's an OutputStream, could you get it to write to a ByteArrayOutputStream and then build a string from that?
i have been able to store the error in a file by using FileOutputStream
FileOutputStream fos = null;
File file = new File("errors.txt");
try
{
fos = new FileOutputStream(file);
}
catch(IOException ioe)
{
System.err.println("redirection not possible: "+ioe);
System.exit(-1);
}
PrintStream ps = new PrintStream(fos);
((ChannelExec)channel).setErrStream(ps);

Categories