Reputation: 297
I can't figure it out how I can send commands via JSch shell channel.
I do this, but it doesn't work:
JSch shell = new JSch();
String command = "cd home/s/src";
Session session = shell.getSession(username, host, port);
MyUserInfo ui = new MyUserInfo();
ui.setPassword(password);
session.setUserInfo(ui);
session.connect();
channel = session.openChannel("shell");
fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream()));
toServer = channel.getOutputStream();
channel.connect();
toServer.write((command + "\r\n").getBytes());
toServer.flush();
and then I read input like this:
StringBuilder builder = new StringBuilder();
int count = 0;
String line = "";
while(line != null) {
line = fromServer.readLine();
builder.append(line).append("\n");
if (line.endsWith(".") || line.endsWith(">")){
break;
}
}
String result = builder.toString();
ConsoleOut.println(result);
Upvotes: 28
Views: 85935
Reputation: 155
When using JSch you have to use an InputStream
for communication from your SSH client to the server and an OutputStream
back from the server to the client. That is probably not very intuitive.
The following examples use piped streams to provide a more flexible API.
Create a JSch session ...
Session session = new JSch().getSession("user", "localhost", port);
session.setPassword("secret");
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
If you want to send multiple commands to a shell you should use the ChannelShell
as follows:
ChannelShell channel = (ChannelShell) session.openChannel("shell");
PipedInputStream pis = new PipedInputStream();
channel.setInputStream(pis);
PipedOutputStream pos = new PipedOutputStream();
channel.setOutputStream(pos);
channel.connect();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new PipedOutputStream(pis)));
writer.write("echo Hello World\n");
writer.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(new PipedInputStream(pos)));
String line = reader.readLine(); // blocking IO
assertEquals("Hello World", line);
With the help of an ByteArrayOutputStream
you can also communicate in a non-blocking way:
ChannelShell channel = (ChannelShell) session.openChannel("shell");
channel.setInputStream(new ByteArrayInputStream("echo Hello World\n".getBytes()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
channel.setOutputStream(baos);
channel.connect();
sleep(1000); // needed because of non-blocking IO
String line = baos.toString();
assertEquals("Hello World\n", line);
If you just want to send one command the ChannelExec
is enough. As you can see the output stream works in the same way like before:
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand("echo Hello World");
PipedOutputStream pos = new PipedOutputStream();
channel.setOutputStream(pos);
channel.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(new PipedInputStream(pos)));
String line = reader.readLine(); // blocking IO
assertEquals("Hello World", line);
Upvotes: 0
Reputation: 345
If it hangs at readLine()
that means either your "while" is never ending (might be unlikely considering your code), or, readLine()
is waiting for its source, namely the IOstream
blocks the thread cause available()!=true
.
I can't quite troubleshoot your code without seeing your debug info. But as an advice, have you tried PipedIntputStream
? The idea is to pipe your console input to "your" output so that you can "write" it. To implement this, you need to initialize the in/out-put.
InputStream in = new PipedInputStream();
PipedOutputStream pin = new PipedOutputStream((PipedInputStream) in);
/**...*/
channel.setInputStream(in);
channel.connect();
/** ...*/
pin.write(myScript.getBytes());
The same goes to your question, how to read console output.
PipedInputStream pout = new PipedInputStream((PipedOutputStream) out);
/**
* ...
*/
BufferedReader consoleOutput = new BufferedReader(new InputStreamReader(pout));
consoleOutput.readLine();
And again, if you are not sure how many lines to read and thus want to use "while", make sure you do something inside while to prevent 1) busy-waiting 2) ending-condition. Example:
while(!end)
{
consoleOutput.mark(32);
if (consoleOutput.read()==0x03) end = true;//End of Text
else
{
consoleOutput.reset();
consoleOutput.readLine();
end = false;
}
}
Upvotes: 13
Reputation: 20976
Usage:
String remoteCommandOutput = exec("ssh://user:pass@host/work/dir/path", "ls -t | head -n1");
String remoteShellOutput = shell("ssh://user:pass@host/work/dir/path", "ls")
shell("ssh://user:pass@host/work/dir/path", "ls", System.out)
shell("ssh://user:pass@host", System.in, System.out);
Upvotes: 0
Reputation: 2724
I realize that this is an old thread, but I have struggled with a similar problem today. This is my solution.
public class ChannelConsole {
// ================================================
// static fields
// ================================================
// ================================================
// instance fields
// ================================================
private Session session;
// ================================================
// constructors
// ================================================
public ChannelConsole(Session session) {
this.session = session;
}
// ================================================
// getters and setters
// ================================================
// ================================================
// public methods
// ================================================
public String execute(String command) throws JSchException {
command = command.trim() + "\n";
ChannelExec channel = (ChannelExec) this.session.openChannel("exec");
channel.setCommand(command);
ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
channel.setOutputStream(responseStream);
channel.connect();
try {
awaitChannelClosure(channel);
} catch (InterruptedException e) {
// no one cares
}
String result = responseStream.toString();
closeQuietly(responseStream);
return result;
}
// ================================================
// private methods
// ================================================
private void awaitChannelClosure(ChannelExec channel) throws InterruptedException {
while (channel.isConnected()) {
Thread.sleep(100);
}
}
private static void closeQuietly(Closeable closeable) {
if (closeable == null) {
return;
}
try {
closeable.close();
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
}
Using this class you can just do something like :
shell = new ChannelConsole(this.session);
String result = shell.execute("quota -v; echo; echo \"Disk storage information:\"; df -hk")
Upvotes: 1
Reputation: 172
try this code :
JSch jsch=new JSch();
System.out.println("Getting session");
Session session=jsch.getSession("root","10.0.0.0",22);
System.out.println("session is ::::"+session.getHost());
// username and password will be given via UserInfo interface.
UserInfo ui = new MyUserInfo("Lab@123", null);
//UserInfo ui = new MyUserInfo(password, null);
session.setUserInfo(ui);
session.setPassword("Lab@123");
Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect(40000);
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand("ls");
channel.connect();
channel.run();
// get I/O streams for remote scp
OutputStream out=channel.getOutputStream();
InputStream in=channel.getInputStream();
String output="";
while (channel.isClosed()!=true) {
try {
output+=streamToString(in);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Output is :::"+output);
channel.disconnect();
session.disconnect();
}
public static String streamToString(InputStream input)throws Exception
{ String output = ""; while(input.available()>0) { output += ((char)(input.read())); } return output; }
public static OutputStream stringToStream(String charset) throws IOException{
byte[] bytes = charset.getBytes();
/*ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
InputStreamReader isr = new InputStreamReader(bais);*/
InputStream is = null;
OutputStream os = null;
try {
is = new ByteArrayInputStream(charset.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//byte[] buf = new byte[1024];
int numRead;
while ( (numRead = is.read(bytes) ) >= 0) {
os.write(bytes, 0, numRead);
}
return os;
Upvotes: -1
Reputation: 21
private void executeRemoteCommandAsSudo(String sudoAs, String password,
String command, int delayInSeconds)
{
logger.info("executeRemoteCommandAsSudo started....");
logger.info("sudoAs=" + sudoAs);
logger.info("command=" + command);
logger.info("delayInSeconds=" + delayInSeconds);
Session session = null;
Channel channel = null;
try {
session = getSession();
channel = session.openChannel("exec");
String sudoCommand = "sudo su - " + sudoAs;
((ChannelExec) channel).setCommand(sudoCommand);
((ChannelExec) channel).setPty(true);
channel.connect();
InputStream inputStream = channel.getInputStream();
OutputStream out = channel.getOutputStream();
((ChannelExec) channel).setErrStream(System.err);
out.write((password + "\n").getBytes());
out.flush();
Thread.sleep(1000);
out.write((command + "\n").getBytes());
out.flush();
Thread.sleep(1000 * delayInSeconds);
out.write(("logout" + "\n").getBytes());
out.flush();
Thread.sleep(1000);
logInfo(channel, inputStream);
out.write(("exit" + "\n").getBytes());
out.flush();
out.close();
Thread.sleep(1000);
} catch (Exception ex) {
logger.error(ex.getMessage());
} finally {
session.disconnect();
channel.disconnect();
}
logger.info("executeRemoteCommandAsSudo completed....");
}
private void logInfo(Channel channel, InputStream in)
{
try {
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0)
break;
logger.info(new String(tmp, 0, i));
}
if (channel.isClosed()) {
logger.info("exit-status: " + channel.getExitStatus());
break;
}
}
} catch (Exception ex) {
logger.error(ex);
}
}
private Session getSession() throws JSchException
{
JSch jsch = new JSch();
logger.info("ftpUser=" + ftpUser);
logger.info("ftpHost=" + ftpHost);
Session session = jsch.getSession(ftpUser, ftpHost, 22);
session.setPassword(ftpPassword);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
return session;
}
Upvotes: 2
Reputation: 4089
try this
Channel channel=session.openChannel("shell");
OutputStream ops = channel.getOutputStream();
PrintStream ps = new PrintStream(ops, true);
channel.connect();
ps.println("mkdir folder");
ps.println("dir");
//give commands to be executed inside println.and can have any no of commands sent.
ps.close();
InputStream in=channel.getInputStream();
byte[] bt=new byte[1024];
while(true)
{
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);
}
if(channel.isClosed())
{
break;
}
Thread.sleep(1000);
channel.disconnect();
session.disconnect();
}
Upvotes: 0
Reputation: 31
With piped input and output streams seems interesting:
JSch jsch = new JSch();
jsch.addIdentity("/home/audrius/.ssh/blablabla", "blablablabla");
String user = "audrius";
String host = "ultrastudio.org";
Session session = jsch.getSession(user, host, 439);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
Channel channel = session.openChannel("shell");
PipedInputStream pip = new PipedInputStream(40);
channel.setInputStream(pip);
PipedOutputStream pop = new PipedOutputStream(pip);
PrintStream print = new PrintStream(pop);
channel.setOutputStream(System.out);
print.println("ls");
Upvotes: 1
Reputation: 117
Following was a quickly written code for my assignment. Not a well done program. But serves its purpose.
The code follows:
public class connectSSH {
public void connect(String dnsName, String privKey) throws IOException {
JSch jSch = new JSch();
try {
//Authenticate through Private Key File
jSch.addIdentity(privKey);
//Give the user and dnsName
Session session = jSch.getSession("root", dnsName, 22);
//Required if not a trusted host
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
System.out.println("Connecting SSH to " + dnsName + " - Please wait for few minutes... ");
session.connect();
//Open a shell
Channel channel=session.openChannel("shell");
channel.setOutputStream(System.out);
//Create a Shell Script
File shellScript = createShellScript();
//Convert the shell script to byte stream
FileInputStream fin = new FileInputStream(shellScript);
byte fileContent[] = new byte[(int)shellScript.length()];
fin.read(fileContent);
InputStream in = new ByteArrayInputStream(fileContent);
//Set the shell script to the channel as input stream
channel.setInputStream(in);
//Connect and have fun!
channel.connect();
} catch (JSchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public File createShellScript() {
String filename = "shellscript.sh";
File fstream = new File(filename);
try{
// Create file
PrintStream out = new PrintStream(new FileOutputStream(fstream));
out.println("#!/bin/bash");
out.println("echo \"hi\" > /tmp/test.info");
out.println("echo \"n\" > /tmp/fdisk.in");
out.println("echo \"p\" >> /tmp/fdisk.in");
out.println("echo \"1\" >> /tmp/fdisk.in");
out.println("echo >> /tmp/fdisk.in");
out.println("echo >> /tmp/fdisk.in");
out.println("echo \"w\" >> /tmp/fdisk.in");
out.println("/sbin/fdisk /dev/sdf < /tmp/fdisk.in");
out.println("mkfs.ext3 /dev/sdf1");
out.println("mkdir /usr/myebs");
out.println("mount /dev/sdf1 /usr/myebs");
out.println("partprobe /dev/sdf1");
out.println("echo \"Success\"");
//Close the output stream
out.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
return fstream;
}
public static void main(String[] args) {
connectSSH ssh = new connectSSH();
String privKey = "/Users/neo/Desktop/mykey.pem";
try {
ssh.connect("yourexampleserver.com", privKey);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Upvotes: 2
Reputation: 1393
Try this:
JSch jsch = new JSch();
try
{
Session session = jsch.getSession("root", "192.168.0.1", 22);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
String command = "lsof -i :80";
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
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();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
Upvotes: 17