How can I execute Linux commands on a remote machine using Java? - java

I have two secured linux servers. In one machine my Java application is running. I need to run Linux commands on second machine from first machine in Java. How might I do this?

Jsch (here) allows you to connect to a remote server using SSH and executes shell commands easily (and lot of other things like SCP, SFTP...). There is not a lot of documentation, but you have a few really helpful implementation examples here (and even an example of what you want to do here).
You can also combine Jsch with Expect4j and this way have a better control on the commands you want to execute (nice example here).

Essentially, you need to open an ssh connection to the other server from within your Java application. The OpenSSH site has some useful information on libraries that will give you ssh support in Java.
It looks like Ganymed SSH-2 for Java is the nicest of the pick there, but I haven't used any of them so you will need to look at what you need.
Once you have an ssh connection, you will be able to run commands just as if you logged in using any other ssh client.

You can do it a number of ways; however, nearly every way involves a network connection.
You could write a client-server pair of Java programs, with the client connection to a server and submitting the command.
You could write your Java to use an existing server, like sshd, telnetd, rsh, ftpd, or a pre-existing other server which allows commands at the remote end.
You could leverage an architecture which handles certain aspects of establishing a client-server pair, like RMI, SOAP, CORBA, etc.
In the end Java supports tons of networking options, so you have more ways of doing this than you think. Just make sure you don't do it in a web browser, as those JVMs are launched sandboxed, and you can't get out of the sandbox without some assistance.

It might be easier to check out Sockets, as you can do what you're trying to do without having to get any external libraries set up.
On the host machine, you want to set up a ServerSocket object, and from the client machine you open a Socket. I don't have time to type up a whole example, but check this out for a simple way to set up a server-host connection over the Internet in Java.
http://zerioh.tripod.com/ressources/sockets.html
Once you get that set up, you want to input your shell command from the ServerSocket on the computer that should execute the command, and do something around the lines of
String command = "get this from the ObjectInputStream attached to your ServerSocket";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(command) ;
pr.waitFor() ;
BufferedReader buffer = new BufferedReader( new InputStreamReader( pr.getInputStream() ) ) ;
String line;
while ( ( line = buffer.readLine() ) != null )
{
System.out.println(line);
}
The tricky part is setting up a realiable host-client connection with the Sockets, but if you're doing something simple you should be fine with the example from the link above.

Related

running ssh and executing commands on remote machines

I am a java developer and am assigned to work on a project in which I need to programmatically ssh into linux boxes and run some unix commands. After the commands have run, the output of the commands should be collected and displayed on the UI.
I saw a library called sshxcute which can be used to accomplish this. My questions are:
Is there a better solution than Java based for this kind of requirements like Nodejs or Ruby on Rails
Can get the real time logs from the system where the command is getting executed than getting the logs are the commands have been run.
Can run multiple parallel process on the machines asynchronously.
You can use sshj. It allows you to open a ssh connection, send commands and read the output.
I used jsch java library
ChannelShell channel = openShellChannel();
OutputStream outputStream = channel.getOutputStream();
PrintStream commander = new PrintStream(outputStream, true);
// Print logs
channel.setOutputStream(System.out, true);
// exec the command
commander.println(command);

Operating terminal session from Java

I am trying to make a terminal emulator in Java. The java program will accept the commands from user, and show its output to them. I can emulate simple commands like 'ls', but I don't know how to handle commands like 'cd'. This is because, I am using exec() method for executing terminal commands. So, all the commands are executed at current directory. The commands like 'cd ..' are executed, but then they have no persistent effect, because each command is separately executed by exec().
Any Ideas How I can emulate a whole session??
If you are executing commands with exec(), you are not writing a terminal emulator; you are writing a shell. In that case, you will need to keep track of things the shell keeps track of, like environment variables and working directory.
If you really want to write a terminal emulator, you would be talking to a shell process through a pseudo-terminal. Then your program would just be keeping track of the things a terminal keeps track of, like the line state and what appears on the screen.
Working with a pseudo-terminal from Java will be a little tricky, because most of the documentation assumes you are using a C api. man pty should get you started. Your Java process will have to open the master side of the pseudo-terminal with FileStream objects. I'm not sure there is a way within Java to get a child process to open the slave side of the pseudo-terminal; you might have to invoke a shell command with exec() that starts another shell command with standard input/output/error redirected to the slave side of the pseudo terminal.
JSch is a pure Java implementation of SSH2.
JSch allows you to connect to an sshd server and use port forwarding, X11 forwarding, file transfer, etc., and you can integrate its functionality into your own Java programs.
http://www.jcraft.com/jsch/
You should really give a try to Ganymed.
Ganymed SSH-2 for Java is a library which implements the SSH-2
protocol in pure Java (tested on J2SE 1.4.2 and 5.0). It allows one to
connect to SSH servers from within Java programs. It supports SSH
sessions (remote command execution and shell access), local and remote
port forwarding, local stream forwarding, X11 forwarding, SCP and
SFTP.
http://www.ganymed.ethz.ch/ssh2/
Ganymed along with apache FTP client you can also download and upload files.
Also there is a inbuilt example code for terminal emulation in Ganymed.
The following is a link to a project which is did using Ganymed along with apache FTP client.
GITHUB
Happy Coding!!

Java SSH Tunneling for an IRC chat

My program connects to an IRC room on freenode.net, it uses port 6667, apparently that port is blocked in my college so the project doesn't work there (I wish I had known that before I proposed that one, but it's due the next week so I can't make a new project now). I read that it was possible to tunnel that connection, but I'm not sure how to do it.
I read I had to use an SSH library but I can't find one that helps me tunneling the connection using a socket.
I found a package called ssh in MindTerm but a really old one, that basically does the process (I think) using these lines:
SSHSocketFactory fact = new SSHSocketFactory("ssh.freessh.biz", 22, new SSHPasswordAuthenticator("freessh", "7QO5dkmg<"));
ventanachat.socket = fact.createSocket(servidorirc, puerto);
It gives me: java.io.IOException: MindTerm do not support SSHv2 yet, enable SSHv1 compatibility in server
So I tried a new version that has ssh2 support, but I just can't get the same process since classes are different here and there's no documentation.
The socket is basically Socket socket = new Socket ("irc.freenode.net", 6667);
I am wondering what library could I use, and how?
You are liable to get into trouble for circumventing blocks of the IRC port.
I've got another idea. Download and install IRC server software on the machine you are doing development on. Then you should be able to connect to it from your client without anything blocking the port. (And if you still run into port problems, just configure the client and server use a different one.)
Alternatively, look at the answers to this SO question: Simple SSH Tunnel in Java
There's a couple of SSH libraries for Java present on the market and most of them support SSH tunneling. We offer SecureBlackbox product (Java edition) which has samples (including tunneling), documentation and support.
Ganymed and Jsch both support SSH tunnelling, and both are free.

How can I determine if another local machine is alive?

Is it possible to make my local computer function as a gateway in Java? I need the other local machines to connect directly to my computer to see if they are alive or not.
You could run a Java server program on your desired PC and let it listen on a port. Then you could use other programs (browser, other Java programs etc.) to connect to this port, and send commands to be executed by the Java server program.
If you just want to see if the PC is turned on or not, I'd just use the ping command though. Or see this answer: How to do a true Java ping from Windows?
Surely it's the other way round? Surely you want to connect to the other machines to see if they're alive? In which case see InetAddress.isReachable().
Try this.
Create a Java Server Socket, which keeps listening to the client at some port.
Write a client in Java which connects to the Server, wrap the connection logic in try-catch block....
If your host is alive the try code is executed which contains the code to connect to the
Server, if this connection process fails you will get UnknownHostException, here you can instead type a message that the connection failed.
You could more easily manage and control this by polling for other devices from a central server. If possible, avoid unnecessary client/agent apps that might tax your development and support resources as well as taking up RAM on the client workstations.
There are many monitoring tools that already do what you want. I'd have a look at Nagios, for example.
If you want to develop your own app, do your own quick troubleshooting, or just get a feel for network discovery tools, then take a look at NMAP. You could, for example, search a subnet for anything that responds to TCP:445 and see what Windows machines are alive.
If you do go the Nmap route, please have a look at Nmap4j on Sourceforge. It's a Java wrapper API that simplifies the work needed to integrate Java and Nmap.
Cheers!

Java Web service using ssh (remote linux connection)

I am more than novice in Linux. Nevertheless, I need to create a Java Web Service hosting in apache server in a Linux system. The Web service must use ssh to connect to a remote machine, create a txt file, execute a prog.exe (compiled C program in MPI) and then retrieve and return a single output value. The only thing that I do not know is how to connect remotely with the Web Service. In a shell will use something like:
ssh username#remotemachine
and then we will get a prompt for password.
Is it possible to send the password along with the ssh command? I have read that it is possible to connect in one shot with public/private keys but this project is my Master Thesis one and as a result, the machines are these of the uni. So, I do not want to mess with the technicians because most of the times simple do not help at all.
Thanks very much
Most Ssh clients will recognize the following
ssh username#remotemachine -pw'YourPassword'
However, I used GanymedeSSH for Java and it had a method like this:
conn = new Connection(servername, 22);
conn.connect();
conn.authenticateWithPassword(username, password);
session = conn.openSession();
And as long as you keep reference to your session, you will be able to use it to execute commands on the remote machine.
You could use the library Jaramiko to get over the problem (instead of calling ssh externally).

Categories