I am following below steps for running commands on ssh server.
Connecting to ssh server
Using devpush command again logging to server (using expectit library for user input prompt).
Finally running remote commands using jsch library.
The issue I am facing is that, my code is going in infinite loop it is able to login to ssh server but not able to run the commands.
Can any one please help me on this as I am using both the libraries for first time.
package com.dmotorworks.cdk;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import net.sf.expectit.*;
import net.sf.expectit.matcher.Matchers;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
public class ShellClient {
public void loginToPabloServer() throws IOException, JSchException{
String hostname="pablo.dmotorworks.com";
String username="gaikwasu";
String password="Nexus#80900";
final String endLineStr=" # ";
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, 22);
session.setPassword(password);
jsch.setKnownHosts("C://Users//gaikwasu//.ssh//known_hosts");
session.connect();
System.out.println("Connected");
Channel channel=session.openChannel("shell");
channel.connect();
Expect expect=new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
.withEchoOutput(System.out)
.withEchoInput(System.err)
.withExceptionOnFailure()
.build();
expect.expect(Matchers.contains("-bash-4.1$"));
expect.send("devpush\n");
expect.expect(Matchers.contains("[sudo] password for"));
expect.send(password+"\n");
DataInputStream dataIn = new DataInputStream(channel.getInputStream());
DataOutputStream dataOut = new DataOutputStream(channel.getOutputStream());
BufferedReader bufferReader= new BufferedReader(new InputStreamReader(dataIn));
dataOut.writeBytes("cd custom\n");
dataOut.writeBytes("ls -lrt\n");
dataOut.flush();
String line=bufferReader.readLine();
while(!line.endsWith(endLineStr)) {
System.out.println(line);
}
channel.disconnect();
session.disconnect();
expect.close();
}
public static void main(String[] args) {
ShellClient shellClient=new ShellClient();
try {
shellClient.loginToPabloServer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Most probably the cause of the infinitive loop is because the Expect instance reads the input data in a separate thread at the same time while you are trying to same data in the main thread.
Try to close the Expect instance before reading the data. It may help.
However, I strongly recommend to keep using the Expect instance after the sending password. ExpectIt can help with extracting the information from the remote command output. For example:
expect.sendLine(password);
expect.expect(Matchers.contains("-bash-4.1$"));
expect.sendLine("cd custom");
expect.expect(Matchers.contains("-bash-4.1$"));
expect.sendLine("ls -lrt");
// the lsResult variable should contain the result of the 'ls -l' command
String lsResult = expect.expect(Matchers.contains("-bash-4.1$")).getBefore();
System.out.println(lsResult);
Please take a look at this example.
Related
I'm using gammu to send sms, and I was wondering if it is possible to send messages at the same time using two or more computer with java app. I tried it 10 times and 1 out of 10 times the message successfully sent from both computer. 9 times only one computer can send the sms with the other one failing to send.
Is there some kind of setting or command so I can send message from both of this computers at the same time? For the config I use the default config from Gammu
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
public class TestingSms {
public static void main(String[] args) {
// TODO Auto-generated method stub
String host = "MY GAMMU IP";
String user = "MY USERNAME";
String password = "MY PASSWORD";
int port = 22;
String sms ="haloo";
JSch jsch = new JSch();
try {
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
ChannelExec exec = (ChannelExec) session.openChannel("exec");
exec.setCommand("gammu sendsms TEXT 08xxxxxxxxxx -text \""+sms+"\"");
exec.setErrStream(System.err);
exec.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
String temp;
while((temp=reader.readLine())!=null) {
System.out.println(temp);
}
exec.disconnect();
session.disconnect();
System.out.println("\n\nFinish");
} catch (JSchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Failed Message:
Warning: No configuration read, using builtin defaults!
No response in specified timeout. Probably phone not connected.
Thank you in advance
Maybe you rather want to use Gammu SMSD for this - it runs on the server and sends/receives messages from/to database. This way you can easily send messages from other hosts just by inserting them to the database.
The error Warning: No configuration read, using builtin defaults! indicates that Gammu didn't find the configuration file, maybe you're running it as different user? Or try to specify path to configuration file using --config parameter.
I am creating a Java HTTP server that checks to make sure a client is not banned before redirecting to the main server. I have already created everything for the server that is needed, I just don't know how to redirect to another port that is running the main server. Here is my code:
package netlyaccesscontrol;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class AllowedCheck {
public static void main(String[] args) {
String line = null;
try {
FileReader reader = new FileReader("Banned.txt");
BufferedReader buffer = new BufferedReader(reader);
ServerSocket s = new ServerSocket(80);
Socket c = s.accept();
String clientIP = c.getInetAddress().toString();
while ((line = buffer.readLine()) != null) {
if (clientIP == line) {
s.close();
} else {
// redirect to main server here
}
}
} catch (FileNotFoundException ex) {
System.out.println("The banned IP address file does not exist.");
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
The redirection that you are thinking of is something supported by HTTP and the browsers. There's a specific HTTP response code that tells the caller to redirect and a way to specify it.
Raw sockets are a low-level network protocol that is not going to support redirection as you expect. The most you might be able to do is have this program be a proxy and, upon success, push all incoming data/outgoing responses to/from the ultimate server. But what you have here is by no means going to cut it.
I am using Jsch library to execute about 1000 different of shell scripts in few linux machines and update the status into a table.
I used jsch exec channel [ChannelExec], it was working only for the single script, if the shell script calls another script, ChannelExec was not giving correct result.
now I am using shell channnel of jsch. it is working well to get output from any kind of shell script.
the problem is, if I execute many shell scripts at once , I am getting all result in one bulk.
there is no way to get one Shell script executed and its result received.
if i want to get individual scripts execution result, I need to login to the machine for each script execution , this is taking very long time.
can somebody post a solution, suggestion on how to go about , login into machine once and execute multiple scripts and receive each script result individually.
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
public class JschShellExample {
public static void main(String[] args) {
try {
JSch jsch = new JSch();
Session session = jsch.getSession("user", "10.32.248.158", 22);
session.setPassword("password");
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
session.setConfig(config);
session.connect(100);
Channel channel = session.openChannel("shell");
OutputStream inputstream_for_the_channel = channel.getOutputStream();
PrintStream commander = new PrintStream(inputstream_for_the_channel, true);
channel.setOutputStream(null);
channel.connect(100);
//shell script
commander.println("cd /user/home/work ; ./checkstaus.sh ; exit");
commander.flush();
System.out.println(channel.getExitStatus());
InputStream outputstream_from_the_channel = channel.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(outputstream_from_the_channel));
String line = null;
StringBuilder sb = new StringBuilder();
boolean isloginStringPassed = false ;
while ((line = br.readLine()) != null) {
sb.append(line.trim());
}
System.out.println("Result ="+sb.toString());
channel.disconnect();
session.disconnect();
System.out.println("completed .. ");
} catch (JSchException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Usually when you connect to a remote machine for the first time and after executing a command you'll get a shell command line prompt printed to the output stream. You can use it as a marker between output of different shell commands.
You may consider using an Expect-like third party library which simplify working with a remote services and capturing output. There a good set of options you can try:
Expect4J
ExpectJ
Expect-for-Java
However, when I was about to solve similar problem I found these libraries are rather old and hard to use in a commercial software. So I created my own and made it available for others. It it called ExpectIt. The advantages of my library it are stated on the project home page.
Here is an example of interacting with a public remote SSH service:
JSch jSch = new JSch();
Session session = jSch.getSession("new", "sdf.org");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("shell");
Expect expect = new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
.withEchoOutput(adapt(System.out))
// .withInputFilters(removeColors(), removeNonPrintable())
.withErrorOnTimeout(true)
.build();
// try-with-resources is omitted for simplicity
channel.connect();
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(": $"));
// finally is omitted
channel.disconnect();
session.disconnect();
expect.close();
You can also take a look a at this example interacting with a Karaf shell which captures individual command output.
I want to test this simpel server-client application on my own machine at home. How can I run this in Eclipse and then see if the other side can see my message. I want to at some point be able to make a chat window that anyone could have on their machine and send messages to anyone that is online that is linked into the chat window.
But first I have to be able to see that I have a connection. Should I install a server on my computer, or someone told me that there was a server already installed on my computer but I just had to have windows turn it on. (Windows 7)
Question: How can I test this client-server on my computer at home?
Code:
Client Side:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import javax.swing.JOptionPane;
public class DateClient {
public static void main(String[] args) throws IOException {
String serverAddress = JOptionPane.showInputDialog(
"Enter IP Address of a machine that is\n" +
"running the date service on port 9090:");
Socket s = new Socket(serverAddress, 9090);
BufferedReader input =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String answer = input.readLine();
JOptionPane.showMessageDialog(null, answer);
System.exit(0);
}
}
Server side:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class DateServer {
public static void main(String[] args) throws IOException {
ServerSocket listener = new ServerSocket(9090);
try {
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out =
new PrintWriter(socket.getOutputStream(), true);
out.println(new Date().toString());
} finally {
socket.close();
}
}
}
finally {
listener.close();
}
}
}
Code I want to Add for new message:
out.println("Hello Doug, how are you!);
This will not show in my message box when it shows up on the screen. Is 127.0.0.1 always the IP address that needs to be entered when testing from eclipse or how would I change this around so that I could let the user determine their own IP address.
You can just open two terminals. For the DateClient, just use localhost or 127.0.0.1 as the address. If you really must use Eclipse, then you can run one of the program from Eclipse and the other from a terminal.
You don't need any server.
In Eclipse (assuming your coding is correct), you can run multiple programs (Java files with a main method) simultaneously.
First, say DateServer -> Run As -> Java Application
Next, say DateClient -> Run As -> Java Application
To run this, you don't need any additional server, but Win 7 might ask you for permissions to unblock these programs from accessing the network. You should say yes to these permissions.
If you want to get a feel of separate client and server, this might be better
Keep the DateClient and DateServer in two different projects
Compile both projects as JARs
Open two different DOS consoles and run these two applications in these separate DOS consoles.
Client Side :
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ClientSide {
public static void main(String[] args) {
try {
Socket s = new Socket("localhost", 1234);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF("Hello");
} catch (IOException ex) {
System.out.println("Connection failed");
}
}
}
Server Side :
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
public class ServerSide {
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(1234);
System.out.println("waiting for connection...");
DataInputStream dis = new DataInputStream(ss.accept().getInputStream());
System.out.println("Successfully Connected\n" + dis.readUTF());
} catch (IOException ex) {
System.out.println("Server Not Started : " + ex);
}
}
}
I'm using Ganymede ssh2 to connect to server from my Java app and do some work there.
It works perfectly but problems are ssh commands that request approval, eg.
a command
stop someService
returns
Are you sure (y/n)?
and after appropriate key stroke (y/n) it moves on.
Currently I'm using implementation given by ssh2 ganymed example, smth like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
public class ConnectUtil(String hostname, String username, String password, String command)
{
try
{
Connection conn = new Connection(hostname);
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(username, password);
if (isAuthenticated == false)
throw new IOException("Authentication failed.");
Session sess = conn.openSession();
sess.execCommand(command);
InputStream stdout = new StreamGobbler(sess.getStdout());
BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
while (true)
{
String line = br.readLine();
if (line == null)
break;
System.out.println(line);
}
sess.close();
conn.close();
}
catch (IOException e)
{
e.printStackTrace(System.err);
}
}
After calling this util class with above mentioned command('stop someService'), it gets stucked at
String line = br.readLine();
and everything breaks after server timeout.
Any ideas on how to solve this issue are more than welcome.
Thanks a lot,
Milos.
Assuming Session has a getStdin() method, you should write the response to the question to that.
Either that or find out if the command that's demanding input has a 'non-interactive' mode that won't prompt.
If you're going to use stdin instead of exec then you have to do session.startShell() first. Read the FAQs.
I use this code...
sess.executeCommand("ena"+'\n' +"pass"+'\n' +"exit"+'\n');