JSch executing more than one linux command at once - java

My aim is to connect to my linux server using a java application and execute a linux command. I have already achieved this using the JSch API but I can't seem to figure out how to execute more than one command at a time.
It's a problem for me because I need to navigate to a certain directory, then execute another command FROM that directory. My application just exits before the second command can be executed in the correct directory.
Here is my method to execute one linux command as a string when it is passed as a parameter and print any output.
public void connect(String command1){
try {
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
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){
ee.printStackTrace();
}
}
channel.disconnect();
session.disconnect();
System.out.println("DONE");
}
catch(Exception e){
e.printStackTrace();
}
}
Any ideas how to do 2 commands at once?

If a normal shell is started on the remote machine, use ; or && constructs to do more things.
As in
cd /home/foo/banana ; do_things
or
cd /home/foo/banan && do_things #do_things will only be run if the cd command is successfull

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 stop the tomcat server on linux using java and JSch?

I have a requirement in automation where I need to stop the tomcat server located at Linux.. How can I do it?. I am trying multiple code-snippets using JSch but those are not working as expected. Can someone please help me here?
Here is my sample code -
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
JSch jsch = new JSch();
session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig(config);
session.connect();
System.out.println("CONNECTED!");
String process = serverGetprocess();
LOG.info("ACTAUL SERVER PROCESS "+process);
commandStopServer = "kill -9" + process;
LOG.info(commandStopServer);
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(commandStopServer);
channel.setInputStream(null);
channel.setOutputStream(System.out, true);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
channel.connect();
Thread.sleep(1000);
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) {
LOG.info("Inside catch of channel closing!");
}
}
channel.disconnect();
return true;
Here is the code to put within set command "pkill -9 -f tomcat" i.e;
((ChannelExec) channel).setCommand("pkill -9 -f tomcat");

Executing multiple commands one after another using java JSch library

I am looking for a solution to set of commands that need to be executed one after another in a sequential order. Again one command should execute only after the previous command is completed its execution.
String command="cd /home/; ls-ltr;"
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(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){}
}
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
System.out.println("DONE");
I tried executing command using ";" for each command but all the command are executed in a single attempt. So, its not working. What can be the possible approach to run each command in the same shell / exec.
I changed the implementation from "exec" to "shell" and update the command with "&&" between each command. Now the following command is executed only after the complete execution of the previous one. That is "&&" works in such a way that, based on the success status of the previous command i.e by checking the exit status which should be "0" else the following command wont be executed.
Updated code:
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");
OutputStream ops = channel.getOutputStream();
PrintStream ps = new PrintStream(ops, true);
channel.connect();
ps.println(command1 + "&&" + command2 + "&&" + command3 +"&&" +command4);
InputStream in=channel.getInputStream();
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();
}
You can use one command after another by appending them with &&. For example,
jschUtil.openChannel("exec");
jschUtil.getExecSshChannel().setCommand("cd /root/Test1/Test2 && mkdir Neel");
Here, Directory Neel will be created inside Test2. If you create 2 separate channel or use the commands one after the other, this will never be possible.

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

JSch - command not being sent to shell?

I'm working on a project to restart something within a screen on a remote server using JSch... however I'm running into an issue. It will send the first 2 commands 100% of the time, but the 3rd command will only be sent some of the time. Any help would be appreciated.
public static void stopServer(String name, String ip, String passwd)
{
try {
Session session = Main.jsch.getSession("user",ip,22);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(passwd);
session.connect();
Channel channel = session.openChannel("shell");
channel.connect();
ChannelShell cs = (ChannelShell) channel;
cs.setPty(true);
DataInputStream dataIn = new DataInputStream(channel.getInputStream());
PrintStream dataOut = new PrintStream(channel.getOutputStream());
dataOut.println("screen -x "+name);
dataOut.flush();
dataOut.println("stop");
dataOut.flush();
String line = dataIn.readLine();
System.out.println(line);
while(true) {
line = dataIn.readLine();
System.out.println(line);
if(line.contains("\"quit\""))
{
break;
}
}
TimeUnit.SECONDS.sleep(1);
dataOut.println("quit");
dataOut.flush();
System.out.println("Shutdown");
dataIn.close();
dataOut.close();
channel.disconnect();
session.disconnect();
}catch(Exception e)
{
e.printStackTrace();
}
}
This sends the screen -x 'name' and the stop 100% of the time from what I've seen, but the 'quit' command only actually gets sent/understood by the console a fraction of the time. Any help would be appreciated!!
I managed to fix this in a way that doesn't use the shell channel, but it is reliable enough that it works:
//Start EXEC
ChannelExec ce = (ChannelExec) session.openChannel("exec");
ce.setCommand("screen -S " + name + " -X stuff 'quit\n'");
ce.setInputStream(null);
ce.setErrStream(System.err);
InputStream in=ce.getInputStream();
ce.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(ce.isClosed()){
if(in.available()>0) continue;
//System.out.println("exit-status: "+ce.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
ce.disconnect();
//STOP EXEC
As much as this doesn't work along the original vein of the problem, it fixed it for me.
If an exception gets thrown sometime before the "quit" command gets sent, then the quit command will never get sent.
If the while loop never breaks, then that will prevent the "quit"
command from being sent too.

Categories