I am trying to do a simple android aplication to send two commands (start and stop xbmc) to my raspberry pi running RaspBMC. I am using jsch library for SSH connection.
Here is my code:
public void onToggleClicked(View view) {
boolean on = ((ToggleButton) view).isChecked();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
dir_ip = prefs.getString("IP_DIR", "");
String[] params = new String[2];
params[0] = dir_ip;
if (!validarIP(dir_ip)){
alert.showAlertDialog(MainActivity.this, "Error",
"La direccion IP no ha sido seleccionada o es erronea. Vaya a Settings y elija una IP", false);
((ToggleButton) view).setChecked(!on);
}
else{
if (on) {
Log.d("AITOR", "START");
params[1] = "sudo initctl stop xbmc";
new sendCommand().execute(params);
} else {
params[1] = "sudo initctl start xbmc";
new sendCommand().execute(params);
}
}
dir_ip = "";
}
class sendCommand extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
JSch jsch = new JSch();
Session session;
try {
session = jsch.getSession("pi", params[0], 22);
session.setPassword("raspberry");
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
// SSH Channel
ChannelExec channelssh = (ChannelExec)
session.openChannel("exec");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
channelssh.setOutputStream(baos);
// Execute command
channelssh.setCommand(params[1]);
channelssh.connect();
channelssh.disconnect();
}
catch (JSchException e) {
Log.d("AITOR", e.getMessage());
}
return null;
}
}
I am not getting any exception or error simply the command is not sent to my rPi. Thanks for the answers!
Try to change your catch clause to fetch all Exception so you can see if there is an exception thrown elsewhere.
catch (Exception e)...
Related
I am using a JSCH -SSH library to execute command in "shell" channel, but unable to find a way
to do 2 things:-
1) How to find whether the command is completely executed on remote unix box ?
2) How to capture the command output in String , instead of printing it on System.out console ?
Below is my code snippet which works fine to display shell command output on system.out
NOTE :I do NOT want to use ,"exec" channel, as it starts a new process for each command and does not remember "session" variables which were exported. I must use "shell" channel.
Below is my code snippet. Any help is appreciated.Thanks for your time.
try{
String commandToRun = "ls /tmp/*.log \n";
if(channel.isClosed())
channel=session.openChannel("shell");
byte[] bytes = commandToRun.getBytes();
ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
channel.setInputStream(bais);
InputStream ins=channel.getInputStream();
channel.connect();
channel.setOutputStream(System.out);//This prints on console. Need 2 capture in String somehow?
//in-efficient way to allow command to execute completely on remote Unix machine
//DO NOT know a better way, to know when command is executed completely
Thread.sleep(5000L);
}
catch(Exception e){
System.out.println("Exception in executeCommand() --->"+ e.getMessage());
e.printStackTrace();
}
My solution may not be needed anymore for the OP, but anyone else who is searching for a solution to cover both conditions 1) waiting for the commands to finish on remote machine; and 2) capturing output as string; you can try this:
public class SshConnectionManager {
private static Session session;
private static ChannelShell channel;
private static String username = "";
private static String password = "";
private static String hostname = "";
private static Session getSession(){
if(session == null || !session.isConnected()){
session = connect(hostname,username,password);
}
return session;
}
private static Channel getChannel(){
if(channel == null || !channel.isConnected()){
try{
channel = (ChannelShell)getSession().openChannel("shell");
channel.connect();
}catch(Exception e){
System.out.println("Error while opening channel: "+ e);
}
}
return channel;
}
private static Session connect(String hostname, String username, String password){
JSch jSch = new JSch();
try {
session = jSch.getSession(username, hostname, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!");
}catch(Exception e){
System.out.println("An error occurred while connecting to "+hostname+": "+e);
}
return session;
}
private static void executeCommands(List<String> commands){
try{
Channel channel=getChannel();
System.out.println("Sending commands...");
sendCommands(channel, commands);
readChannelOutput(channel);
System.out.println("Finished sending commands!");
}catch(Exception e){
System.out.println("An error ocurred during executeCommands: "+e);
}
}
private static void sendCommands(Channel channel, List<String> commands){
try{
PrintStream out = new PrintStream(channel.getOutputStream());
out.println("#!/bin/bash");
for(String command : commands){
out.println(command);
}
out.println("exit");
out.flush();
}catch(Exception e){
System.out.println("Error while sending commands: "+ e);
}
}
private static void readChannelOutput(Channel channel){
byte[] buffer = new byte[1024];
try{
InputStream in = channel.getInputStream();
String line = "";
while (true){
while (in.available() > 0) {
int i = in.read(buffer, 0, 1024);
if (i < 0) {
break;
}
line = new String(buffer, 0, i);
System.out.println(line);
}
if(line.contains("logout")){
break;
}
if (channel.isClosed()){
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee){}
}
}catch(Exception e){
System.out.println("Error while reading channel output: "+ e);
}
}
public static void close(){
channel.disconnect();
session.disconnect();
System.out.println("Disconnected channel and session");
}
public static void main(String[] args){
List<String> commands = new ArrayList<String>();
commands.add("ls -l");
executeCommands(commands);
close();
}
}
This solution is also useful if you need to send multiple commands at a time and keep the channel open to reuse it later.
For 2) u can use ByteArrayOutputStream
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
channel.setOutputStream(baos);
and then create new string from new String(baos.toByteArray())
For 1 have you tried to use 2>&1 at the end of your command?
String commandToRun = "ls /tmp/*.log 2>&1 \n";
Taking the example provided by Mihail, other info on the internets, and the feedback from Martin, here's a reworked solution using exec. Note that opening a session allows multiple commands to be sent, each one opening it's own channel for input/output.
Rant:I really dislike having to get the process' OUTPUT stream to write to. What an annoying paradigm (at least for me). What I wanted is the processes input stream to write my output to, and had an amazingly difficult time working out that it's inverted. Is it just me or does the following (pseudocode) not make way more sense??
channel.getInputStream().write("here's some text to write into my channel.");
String ret = channel.getOutputStream().getOutput();
Anyways, thanks to Mihail and Martin for their comments / input.
public class SSHConnectionManager {
private Session session;
private String username = "user";
private String password = "password";
private String hostname = "myhost";
public SSHConnectionManager() { }
public SSHConnectionManager(String hostname, String username, String password) {
this.hostname = hostname;
this.username = username;
this.password = password;
}
public void open() throws JSchException {
open(this.hostname, this.username, this.password);
}
public void open(String hostname, String username, String password) throws JSchException{
JSch jSch = new JSch();
session = jSch.getSession(username, hostname, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no"); // not recommended
session.setConfig(config);
session.setPassword(password);
System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!");
}
public String runCommand(String command) throws JSchException, IOException {
String ret = "";
if (!session.isConnected())
throw new RuntimeException("Not connected to an open session. Call open() first!");
ChannelExec channel = null;
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
channel.setInputStream(null);
PrintStream out = new PrintStream(channel.getOutputStream());
InputStream in = channel.getInputStream(); // channel.getInputStream();
channel.connect();
// you can also send input to your running process like so:
// String someInputToProcess = "something";
// out.println(someInputToProcess);
// out.flush();
ret = getChannelOutput(channel, in);
channel.disconnect();
System.out.println("Finished sending commands!");
return ret;
}
private String getChannelOutput(Channel channel, InputStream in) throws IOException{
byte[] buffer = new byte[1024];
StringBuilder strBuilder = new StringBuilder();
String line = "";
while (true){
while (in.available() > 0) {
int i = in.read(buffer, 0, 1024);
if (i < 0) {
break;
}
strBuilder.append(new String(buffer, 0, i));
System.out.println(line);
}
if(line.contains("logout")){
break;
}
if (channel.isClosed()){
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee){}
}
return strBuilder.toString();
}
public void close(){
session.disconnect();
System.out.println("Disconnected channel and session");
}
public static void main(String[] args){
SSHConnectionManager ssh = new SSHConnectionManager();
try {
ssh.open();
String ret = ssh.runCommand("ls -l");
System.out.println(ret);
ssh.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I am trying to send some commands to a router and trying to read the console output. But the problem is every time i send a new command i get the same output. I tried creating a new session after every command is executed but I still get the same output. I got a sample online and modified it according to my needs. When i run it as a standalone class, it works perfectly. But when deployed on a server, it just doesn't seem to work right. To be honest, I am only its only been a day or two I have used the JSCH and documentation is very sparse.
This is how my code reads:
private void writeCommand(String command) throws IOException, JSchException {
Channel channel = getChannel();
((ChannelExec) channel).setCommand(command.getBytes());
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
readChannelOutput(channel);
}
private void readChannelOutput(Channel channel) {
byte[] buffer = new byte[1024];
try {
InputStream inputStream = channel.getInputStream();
channel.connect();
while (true) {
while (inputStream.available() > 0) {
int i = inputStream.read(buffer, 0, 1024);
if (i < 0) {
break;
}
deviceOut.updateDeviceOutput(new String(buffer, 0, i));
}
if (channel.isClosed()) {
break;
}
}
disconnect();
} catch(IOException e) {
e.printstacktrace();
} catch (JSchException e) {
e.printstacktrace();
}
}
public Session getSession () throws Exception {
if (session == null || !session.isConnected()) {
session = connect(getUserid(), getIpaddress(), getPassword(), getPort());
}
return session;
}
protected Session connect(String userName, String hostname, String password, int port) throws Exception {
JSch jSch = new JSch();
try {
session = jSch.getSession(userName, hostname, port);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
logger.debug("Connecting SSH to " + getIpaddress() + " - Please wait for few seconds... ");
session.connect();
logger.debug("Connected!");
if (session.isConnected()) {
setConnectionState(DeviceConnection.LOGIN_COMPLETE);
} else {
setConnectionState(DeviceConnection.LOGIN_FAILED);
throw new Exception("Failed to login to device");
}
deviceOut = new DeviceOutput(getLogger());
return session;
} catch (JSchException e) {
disconnect();
e.printstacktrace();
} catch (PalException e) {
disconnect();
e.printstacktrace();
}
}
The commands that I am trying to send are
term len 512
and
show running-config | include hostname
But the output just stays the same. The first command should not even have any ouput to be honest. Is there anything I am doing wrong?
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 privateKey = "C:\\test\\key";
jsch.addIdentity(privateKey);
String host = null;
host = "192.168.102.211";
Session session = jsch.getSession("chef-admin", host, 22);
Channel channel = session.openChannel("shell");
try
{
String cmd = "sudo su";
String command = "chef-client";
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);
if (i < 0)
break;
String str = new String(bt, 0, i);
System.out.println("valueeeeeeeeeeeeeeee is " + i);
System.out.print(str);
}
System.out.println("before channel");
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (channel != null) {
System.out.println("finally");
channel.disconnect();
session.disconnect();
System.out.println(channel.isConnected());
}
}
I'm trying to use jsch to get the output of commands send hrough SSH. My problem is that I need to get the result of the command into a String in order to use it later. For exemple if I send the command "ls" I want the name of the files in the folder in a string.
How can I do that ?
Here is my code :
import com.jcraft.jsch.*;
public class SSHCommand2 {
public static void main(String[] args) {
String host="host";
String user="user";
String password="password";
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("shell");
((ChannelShell) channel).setPty(true);
OutputStream inputstream_for_the_channel = channel.getOutputStream();
PrintStream commander = new PrintStream(inputstream_for_the_channel, true);
channel.setOutputStream(System.out, true);
channel.connect();
commander.println("ls");
if(channel.isClosed()){
//if(in.available()>0) continue;
System.out.println("exit-status: "+channel.getExitStatus());
//break;
}
do {
Thread.sleep(1000);
} while(!channel.isEOF());
session.disconnect();
}
catch(Exception e)
{
e.printStackTrace();
}
}
this is how I read the output of my command
Edit
1) Method to Connect to the server:
public void connect (final String host){
if(host.isEmpty())
return;
hostname = host;
try{
JSch jsch=new JSch();
String user ="yourUserName";
String host = "yourHost";
Session myLocalSession=jsch.getSession(user, host, 22);
//myLocalSession=jsch.getSession(user, "192.168.1.104", 22);
myLocalSession.setPassword("yourPassword");
myLocalSession.setConfig("StrictHostKeyChecking", "no");
myLocalSession.connect(5000); // making a connection with timeout.
myChannel = myLocalSession.openChannel("shell");
InputStream inStream = myChannel.getInputStream();
OutputStream outStream = myChannel.getOutputStream();
toChannel = new PrintWriter(new OutputStreamWriter(outStream), true);
myChannel.connect();
readerThread(new InputStreamReader(inStream));
Thread.sleep(100);
sendCommand("cd "+path);
}
catch(JSchException e){
String message = e.getMessage();
if(message.contains("UnknownHostException"))
myParser.print(">>>>> Unknow Host. Please verify hostname.");
else if(message.contains("socket is not established"))
myParser.print(">>>>> Can't connect to the server for the moment.");
else if(message.contains("Auth fail"))
myParser.print(">>>>> Please verify login and password");
else if(message.contains("Connection refused"))
myParser.print(">>>>> The server refused the connection");
else
System.out.println("*******Unknown ERROR********");
System.out.println(e.getMessage());
System.out.println(e + "****connect()");
}
catch(IOException e)
{
System.out.println(e);
myParser.print(">>>>> Error when reading data streams from the server");
}
catch(Exception e){
e.printStackTrace();
}
}
2) Method to send a command to the server
public void sendCommand(final String command)
{
if(myLocalSession != null && myLocalSession.isConnected())
{
try {
toChannel.println(command);
} catch(Exception e){
e.printStackTrace();
}
}
}
3) Thread method that read answer from the server
void readerThread(final InputStreamReader tout)
{
Thread read2 = new Thread(){
#Override
public void run(){
StringBuilder line = new StringBuilder();
char toAppend = ' ';
try {
while(true){
try {
while (tout.ready()) {
toAppend = (char) tout.read();
if(toAppend == '\n')
{
System.out.print(line.toString());
line.setLength(0);
}
else
line.append(toAppend);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("\n\n\n************errorrrrrrr reading character**********\n\n\n");
}
Thread.sleep(1000);
}
}catch (Exception ex) {
System.out.println(ex);
try{
tout.close();
}
catch(Exception e)
{}
}
}
};
read2.start();
}
You can use a bufferedReader with the InputStreamReader and read line by line. I use an infinite loop and pause for one second after each failed attempt to read (nothing from the server).
Let's say that the three method are in SessionB class. Example:
SessionB testConnexion = new SessionB();
testConnexion.connect();
testConnexion.sendCommand("cd myFolder");
testConnexion.sendCommand("ls");
You should get the list of file in your console.
If you need, to be able to interact (send a command depending of the output), check my post here.
I'm trying to get a response from a command sent through ssh. I connect using JSch lib. Connection is estabilished but getting no response back from the command sent.
public void openSSH(
String username,
String password,
String hostname,
int port) throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, 22);
this.session = session;
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
}
public String runCommand(String command) throws Exception {
// SSH Channel
ChannelExec channelssh = (ChannelExec) session.openChannel("exec");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream in = channelssh.getInputStream();
channelssh.setOutputStream(baos);
// Execute command
channelssh.setCommand(command);
channelssh.connect();
System.out.println("Unix system connected...");
byte[] tmp = new byte[1024];
while (true){
while (in.available() > 0) {
Log.v("running", "line"); // won't work
int i = in.read(tmp, 0, 1024);
if (i < 0) {
break;
}
String line = new String(tmp, 0, i);
System.out.println("Unix system console output: " +line);
channelssh.disconnect();
}
}
}
private class AsyncTaskOne extends AsyncTask<Void, Void, Boolean> {
#Override
protected Boolean doInBackground(Void... params) {
try {
openSSH("login", "pass", "10.10.10.80", 22 );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
protected void onPostExecute(Boolean value) {
if (value) {
try {
runCommand("ls -llh");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Please check if your inputStream is available actually.From my understanding the problem is that your inputStream doesn;t give you anything so instead of
InputStream in = channelssh.getInputStream();
// channelssh.setOutputStream(baos);
comment this line and see if there is actually something here.
Also how are you sure that you are connected?
The right way to set the command is this so please do this:
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command);