unable to execute a .sh script with Jsch - java

i'm trying to execute a script shell in a unix server from my java application (on my windows seven station) using the ssh api Jsch.
the script shell i'm using "start_lm" is a C binary.
this is the code i'm using (it's from the Jsch website exemples)
try{
JSch jsch=new JSch();
Session session=jsch.getSession(user, host, 22);
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
String command="user/psi/start_lm";
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
channel.setInputStream(null);
((ChannelExec)channel).setErrStream(System.err);
InputStream in=channel.getInputStream();
channel.connect();
while(true){
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channel.disconnect();
session.disconnect();
}
the error i'm getting is
exit-status: -1 what does it mean
thanks for ure help.

There's the problem I believe
". ./start_lm.sh
It should be below provided script present in current directory
"./start_lm.sh
as exit status 127 says
127 "command not found" illegal_command

String command="/bin/sh /user/psi/start_lm.sh";
Please try the above, for jsch might be using an non-interactive shell.

Related

communicate to virtual serial port after SSH

I want to communicate to a virtual Serial Port of my server . Steps involved in this is.
1.SSH in to iLO
2.enter vsp command
3.A virtual serial port session is opened
4.it asks for server credentials and then
it gives us a server terminal experience we can send any
command as we do in a terminal opened in the server itself
So my aim is to automate all the above steps in any way from java.
I have completed the first two steps via jsch but once it enters into virtual serial port session im not able to communicate .
I also tried automating the terminal commands using expect for linux in expect even I see the same pattern once it enters into VSP session I'm not able to communicate I tried autoexpect also it didn't work
Below is my jsch code
public static void main(String[] args) {
String host="10.10.100.209";
String user="administrator";
String password="2xR3M0t3$$";
String command1="vsp";
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");
InputStream in = channel.getInputStream();
channel.setCommand("vsp");
OutputStream out = channel.getOutputStream();
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("out"+new String(tmp, 0, i));
}
if(channel.isClosed()){
System.out.println("exit-status: "+channel.getExitStatus());
break;
}
}
channel.disconnect();
Now my question is how to communicate to virtual serial port after I ssh into my iLO.
Use ChannelShell instead of ChannelExec.
ChannelShell is like using interactive shell.
ChannelExec is like executing shell script.
Your use case seems to be interactive.

How to pass control from local machine to Virtual machine through any scripting language?

I am trying to build a selenium(Java) script where it connects to virtual machine through RDP from local machine and I need to run some commands from current script in virtual machine after connecting to it. The problem I am facing is that control from local machine is not going into virtual machine because of which I am not able to run any scripts or commands in it.Please let me know how to pass control from local machine to virtual machine.To be more specific will my selenium script which is running in my local machine be able to perform any operations in the virtual machine which is opened by same selenium script running in local machine.
It may not be possible. your script may invoke RDP protocol to invoke VM but VM is the separate instance it has it own kernel and user space. The script you run will be in different kernel and user space. Both are not shared the same kernel and user space to access the value between the spaces.
If your VM is linux, you can take a control by using jcraft.
Note: You should have SSH enabled and local IP access to 22 port in VM.
Download jcraft from maven central repo https://mvnrepository.com/artifact/com.jcraft/jsch
public class ssh {
/**
* JSch Example Tutorial
* Java SSH Connection Program
*/
#Test
public static void connection(String host,String user, String password, String command) {
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(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.run();
channel.disconnect();
session.disconnect();
System.out.println("DONE");
}catch(Exception e){
}
}
}
Connect your VM by providing Host address of your server, username, password, and command you want to execute in it.
(Ex)
public class start{
static WebDriver driver;
public static void main(String[], args)
{
//connect your VM by using method from ssh class
ssh.connection("10.200.10.1", "userName", "password", "sudo service jenkins start");
//execute selenium command once application started
driver.findElement(By.xpath(".//*[#id='usr']")).sendKeys("Stack");
//execute another command inside VM
ssh.connection("10.200.10.1", "userName", "password", "cd /var/lib/jenkins/workspace && ls");
}
}

Jsch Java progam to pass arguements to a linux process

I have a binary executable file named as "datasimulator" that runs in a remote linux machine which starts an interactive process where a user can provide input and get its corresponding output like below -
[root#host]$ ./datasimulator
> set country USA //user passing this command
Country set to USA //response from process
> set country Canada
Country set to Canada
>exit
Thank you for using datasimulator.
[root#host]$
I am trying to automate this process using java jsch utility where through my java program I can pass input and get the output back to my program. Though I am able to start the datasimulator through jsch ssh connection but not able to pass input to this simulator process. Kindly help.
Below is the java program which I am trying to use -
JSch jsch = new JSch(); session = jsch.getSession(username, host, 22);
session.setPassword(password);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
channel=session.openChannel("shell");
OutputStream ops = channel.getOutputStream();
ps = new PrintStream(ops, true);
channel.connect();
ps.println("cd /path/To/datasimulator/ && ./datasimulator");
ps.println("Country set to USA");
Thread.sleep(5000);
ps.println("Country set to Canada");
Thread.sleep(5000);
ps.close();
channel.disconnect();
session.disconnect();
This program starts the datasimulator but not able to execute next consecutive commands successfully.

Shell ping command with source option is failing when executed using JSch setCommand

I'm testing short ping test program. If I set simple ping command, "ping y.y.y.y -c 5 -s 500 " into setCommand() function, it works as designed. But if I add addition ping options, "ping source x.x.x.x host y.y.y.y -c 5 -s 500", I got
ping: unknown host source
message back. If I manually execute both commands from the x-terminal, the both commands works fine.
I need to make the program to ping from different source interface IPs. What is the difference between two commands using JSch setCommand?
ping y.y.y.y -c 5 -s 500 (working)
ping source x.x.x.x host y.y.y.y -c 5 -s 500 (not working)
Code:
public static void main(String[] arg){
try{
JSch jsch=new JSch();
String host=null;
if(arg.length>0){
host=arg[0];
}
else{
host=JOptionPane.showInputDialog("Enter username#hostname",
System.getProperty("user.name")+
"#localhost");
}
String user=host.substring(0, host.indexOf('#'));
host=host.substring(host.indexOf('#')+1);
Session session=jsch.getSession(user, host, 22);
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
// this command works
// String command = "ping 20.5.1.15 -c " + count + " -s " + size;
// this command not working
String command = "ping source 20.5.1.10 host 20.5.1.15 -c " + count + " -s
" + size;
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()){
if(in.available()>0) continue;
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);
}
Your ping source x.x.x.x host y.y.y.y syntax seems strange to me. But I will trust you that it works in the terminal.
The ping command probably depends on some environment variable or other configuration to resolve the source address.
The "exec" channel in the JSch (rightfully) does not allocate a pseudo terminal (PTY) for the session. As a consequence a different set of startup scripts is (might be) sourced. And/or different branches in the scripts are taken, based on absence/presence of the TERM environment variable. So the environment might differ from the interactive session you use with your SSH client.
If this breaks the ping command, it's clearly misconfiguration on the server-side, not JSch fault. The ping is not an interactive command, so it should work even on the non-interactive session. You should find out what is it that breaks the ping and fix your startup scripts accordingly.
To verify that this is the root cause, disable the pseudo terminal allocation in your SSH client. For example in PuTTY, it's Connection > SSH > TTY > Don't allocate a pseudo terminal. Then go to Connection > SSH > Remote command and ether your ping source ... command. Check Session > Close window on exit > Never and open the session.
Another (not recommended) approach is to force the pseudo terminal allocation for the "exec" channel using the .setPty method:
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setPty(true);
Using the pseudo terminal to automate a command execution can bring you nasty side effects. See for example Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?
This is a special case of this common problem:
Certain Unix commands fail with "... not found", when executed through Java using JSch

How to create a bot that simulate an SSH shell user interaction?

I'm trying to realize a bot that simulates an user that write/read on a ssh console in Java.
I'm using the JSCH library to manage the ssh connection.
This is the code from which I started:
JSch jsch = new JSch();
Session session = jsch.getSession(username, ipAddress, port);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect(connectionTimeoutInMillis);
Channel channel = session.openChannel("shell");
InputStream is = new InputStream();
OutputStream out= new OutputStream();
channel.setInputStream(is);
channel.setOutputStream(out);
channel.connect();
channel.disconnect();
is.close();
out.close();
session.disconnect();
Obviously the InputStream and OutputStream in the code are wrong, I need to use something that the bot can use to send a String (a command line) and to receive a String(the result of the command execution), what type of streams should I use to obtain this?
Furthermore I noticed that if I send a command and use the System.out as output stream in many cases the output is empty because (I'm almost sure about this) the Java application terminates before that the command execution has produced the result. What is the best practice to tell to JSCH channel listener "wait till the command execution has completed" and then go on? I could use a Thread.sleep(someTime) after the command execution but I don't like much it for obvious reasons.
Consider using a third-party Expect-like Java library to ease the interaction with a remote shell. Here is a good set of options you can try:
Expect4J
ExpectJ
Expect-for-Java
You can also take a look at my own open source project which I created some time ago as the successor to the existing ones. It's called ExpectIt. The advantages of my library are stated on the project home page.
Here is an example of interacting with a public remote SSH service using JSch. It should be easy to adopt it for your use case.
JSch jSch = new JSch();
Session session = jSch.getSession("new", "sdf.org");
session.connect();
Channel channel = session.openChannel("shell");
Expect expect = new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
.withErrorOnTimeout(true)
.build();
try {
expect.expect(contains("[RETURN]"));
expect.sendLine();
String ipAddress = expect.expect(regexp("Trying (.*)\\.\\.\\.")).group(1);
System.out.println("Captured IP: " + ipAddress);
expect.expect(contains("login:"));
expect.sendLine("new");
expect.expect(contains("(Y/N)"));
expect.send("N");
expect.expect(regexp(": $"));
expect.send("\b");
expect.expect(regexp("\\(y\\/n\\)"));
expect.sendLine("y");
expect.expect(contains("Would you like to sign the guestbook?"));
expect.send("n");
expect.expect(contains("[RETURN]"));
expect.sendLine();
} finally {
session.close();
ssh.close();
expect.close();
}
Here is the link to the complete workable example.

Categories