Running shell script using JSch with sudo option [duplicate] - java

Using jsch
when i run the following cmd 'sudo su -' the program hangs
[TestNG] Running:
C:\Users\brian.crosby\AppData\Local\Temp\testng-eclipse-952620154\testng-customsuite.xml
[root#tbx2-toy-1 ~]#
It looks like the "sudo su -" worked becasue the output states "[root#tbx2-toy-1 ~]#" but when i send it another cmd it is unresponsive.
heres the code:
package com.linux;
import java.io.InputStream;
import org.testng.annotations.*;
import com.jcraft.jsch.*;
import com.thoughtworks.selenium.*;
public class LinuxConnection extends SeleneseTestBase{
String host = null;
private StringBuilder strFileData;
String randomFileName = null;
public String getFileData() {
return strFileData.toString();
}
public String getRandomFileName() {
return randomFileName;
}
public LinuxConnection() {
strFileData = new StringBuilder();
}
#Test
public void createUpdateTBX2FileData(String command)throws Exception {
try {
JSch jsch = new JSch();
host = "brian-crosby#************.net";
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();
ChannelExec channel = (ChannelExec)session.openChannel("exec");
((ChannelExec)channel).setPty(true);
((ChannelExec) channel).setCommand(command);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
channel.connect();
byte[] tmp = new byte[2048];
while (in.read(tmp, 0, 2048) > 0) {
String str = new String(tmp);
strFileData.append(str);
System.out.println(strFileData);
}
in.close();
channel.disconnect();
session.disconnect();
} catch (Exception e) {
System.out.println(e);
}
}
public static class MyUserInfo implements UserInfo {
public String getPassword() {
return "********";
}
public boolean promptYesNo(String str) {
str = "Yes";
return true;
}
String passwd;
public String getPassphrase() {
return null;
}
public boolean promptPassphrase(String message) {
return true;
}
public boolean promptPassword(String message) {
passwd = "*******";
return true;
}
public void showMessage(String message) {
}
}
}
Here is where i am sending the cmds:
package com.linux;
import org.testng.annotations.*;
public class testLinuxConnection {
#Test
public void testLinux() throws Exception{
LinuxConnection obj = new LinuxConnection();
String command = "touch tester1.txt; sudo su -; rm tester1.txt;";
obj.createUpdateTBX2FileData(command);
}
}
Again i have spent hours on google trying to find a solution but was unsuccessful
Any help is appreciated

You are code is missing the rest of the code needed for this to run. You need to initialize the type of channel you need out of the initialized session object. Since you need to be able to run more than one command after each other, you need a Shell type channel:
You should check JSch's examples (i.e. Shell.java), here it is for a quick reference:
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/**
* This program enables you to connect to sshd server and get the shell prompt.
* $ CLASSPATH=.:../build javac Shell.java
* $ CLASSPATH=.:../build java Shell
* You will be asked username, hostname and passwd.
* If everything works fine, you will get the shell prompt. Output will
* be ugly because of lacks of terminal-emulation, but you can issue commands.
*
*/
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;
public class Shell{
public static void main(String[] arg){
try{
JSch jsch=new JSch();
//jsch.setKnownHosts("/home/foo/.ssh/known_hosts");
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);
String passwd = JOptionPane.showInputDialog("Enter password");
session.setPassword(passwd);
UserInfo ui = new MyUserInfo(){
public void showMessage(String message){
JOptionPane.showMessageDialog(null, message);
}
public boolean promptYesNo(String message){
Object[] options={ "yes", "no" };
int foo=JOptionPane.showOptionDialog(null,
message,
"Warning",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
return foo==0;
}
// If password is not given before the invocation of Session#connect(),
// implement also following methods,
// * UserInfo#getPassword(),
// * UserInfo#promptPassword(String message) and
// * UIKeyboardInteractive#promptKeyboardInteractive()
};
session.setUserInfo(ui);
// It must not be recommended, but if you want to skip host-key check,
// invoke following,
// session.setConfig("StrictHostKeyChecking", "no");
//session.connect();
session.connect(30000); // making a connection with timeout.
Channel channel=session.openChannel("shell");
// Enable agent-forwarding.
//((ChannelShell)channel).setAgentForwarding(true);
channel.setInputStream(System.in);
/*
// a hack for MS-DOS prompt on Windows.
channel.setInputStream(new FilterInputStream(System.in){
public int read(byte[] b, int off, int len)throws IOException{
return in.read(b, off, (len>1024?1024:len));
}
});
*/
channel.setOutputStream(System.out);
/*
// Choose the pty-type "vt102".
((ChannelShell)channel).setPtyType("vt102");
*/
/*
// Set environment variable "LANG" as "ja_JP.eucJP".
((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP");
*/
//channel.connect();
channel.connect(3*1000);
}
catch(Exception e){
System.out.println(e);
}
}
public static abstract class MyUserInfo
implements UserInfo, UIKeyboardInteractive{
public String getPassword(){ return null; }
public boolean promptYesNo(String str){ return false; }
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return false; }
public boolean promptPassword(String message){ return false; }
public void showMessage(String message){ }
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo){
return null;
}
}
}

Related

Java - Getting corrupted JPG while uploading using FTP connection?

The following code is being used to upload three JPG-Image files using FTP in JAVA.
The files are uploaded and confirmed with a "successful"-message, but the files are corrupted. The small tiny thumbnails-files are partly readable (top quarter).
I tried searching the net and added
setFileType(FTPClient.BINARY_FILE_TYPE);
But the problem still occurs :(
Could somebody have a look at it and give me a hint or advice ?
Code:
package de.immozukunft.programs;
import java.io.*;
import java.util.Locale;
import java.util.ResourceBundle;
import org.apache.commons.net.ftp.FTPClient;
/**
* This class enables the ability to connect and trasfer data to the FTP server
*/
public class FtpUpDown {
static Locale locale = new Locale("de"); // Locale is set to "de" for
// Germany
static ResourceBundle r = ResourceBundle.getBundle("Strings", locale); // ResourceBundle
// for
// different
// languages
// and
// String
// Management
// FTP-Connection properties
static String host = "IP-address"; //Host
static String username = "username"; // Username
static int port = 21; //Port
static String password = "password"; // Password
/**
* <h3>FTP-connection tester</h3>
*
*/
public static boolean connect() {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.connect(host, port);
ftpClient.login(username, password);
ftpClient.logout();
ftpClient.disconnect();
} catch (Exception e) {
// e.printStackTrace();
System.err.println("Unable to connect"); // TODO String einfügen
return (false);
}
System.out.println("Connection established"); // TODO String einfügen
return (true);
}
/**
* <h3>FTP-Status</h3>
*
* #return
* #throws IOException
*/
static public String getStatus() {
if (connect()) {
return (r.getString("successConnectFTP"));
} else {
return (r.getString("unableToConnectFTP"));
}
}
/**
* <h3>FTP-filelist</h3>
*
* #return String-Array der Dateinamen auf dem FTP-Server
*/
public static String[] list() throws IOException {
FTPClient ftpClient = new FTPClient();
String[] filenameList;
try {
ftpClient.connect(host, port);
ftpClient.login(username, password);
filenameList = ftpClient.listNames();
ftpClient.logout();
} finally {
ftpClient.disconnect();
}
return filenameList;
}
/**
* <h3>FTP-Client-Download:</h3>
*
* #return true falls ok
*/
public static boolean download(String localResultFile,
String remoteSourceFile, boolean showMessages) throws IOException {
FTPClient ftpClient = new FTPClient();
FileOutputStream fos = null;
boolean resultOk = true;
try {
ftpClient.connect(host, port);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
resultOk &= ftpClient.login(username, password);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
fos = new FileOutputStream(localResultFile);
resultOk &= ftpClient.retrieveFile(remoteSourceFile, fos);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
resultOk &= ftpClient.logout();
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {/* nothing to do */
}
ftpClient.disconnect();
}
return resultOk;
}
/**
* <h3>FTP-Client-Upload:</h3>
*
* #param localSourceFile
* The source of local file
* #param remoteResultFile
* Set the destination of the file
* #param showMessages
* If set on TRUE messages will be displayed on the console
* #return true Returns If successfully transfered it will return TRUE, else
* FALSE
*/
public static boolean upload(String localSourceFile,
String remoteResultFile, boolean showMessages) throws IOException {
FTPClient ftpClient = new FTPClient();
FileInputStream fis = null;
boolean resultOk = true;
try {
ftpClient.connect(host, port);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
resultOk &= ftpClient.login(username, password);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
fis = new FileInputStream(localSourceFile);
resultOk &= ftpClient.storeFile(remoteResultFile, fis);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
resultOk &= ftpClient.logout();
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {/* nothing to do */
}
ftpClient.disconnect();
}
return resultOk;
}
// Setter and Getter-methods
public static String getHost() {
return host;
}
public static void setHost(String host) {
FtpUpDown.host = host;
}
public static String getUsername() {
return username;
}
public static void setUsername(String username) {
FtpUpDown.username = username;
}
public static int getPort() {
return port;
}
public static void setPort(int port) {
FtpUpDown.port = port;
}
public static String getPassword() {
return password;
}
public static void setPassword(String password) {
FtpUpDown.password = password;
}
}
greets
THE-E
So I finally figured out what the problem was.
The problem was caused by the order of setFileType(FTPClient.BINARY_FILE_TYPE). It needs to be positioned in the upload()-method after the fis = new FileInputStream(localSourceFile) and before the ftpClient.storeFile(remoteResultFile, fis)
So the full working code is:
import java.io.*;
import java.util.Locale;
import java.util.ResourceBundle;
import org.apache.commons.net.ftp.FTPClient;
/**
* This class enables the ability to connect and trasfer data to the FTP server
*/
public class FtpUpDown {
static Locale locale = new Locale("de"); // Locale is set to "de" for
// Germany
static ResourceBundle r = ResourceBundle.getBundle("Strings", locale); // ResourceBundle
// for
// different
// languages
// and
// String
// Management
// FTP-Connection properties
static String host = "IP-Address"; // IP-address
static String username = "username"; // Username
static int port = 21; // Port
static String password = "password"; // Password
/**
* <h3>FTP-connection tester</h3>
*
*/
public static boolean connect() {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(host, port);
ftpClient.login(username, password);
ftpClient.logout();
ftpClient.disconnect();
} catch (Exception e) {
// e.printStackTrace();
System.err.println("Unable to connect"); // TODO String einfügen
return (false);
}
System.out.println("Connection established"); // TODO String einfügen
return (true);
}
/**
* <h3>FTP-Status</h3>
*
* #return
* #throws IOException
*/
static public String getStatus() {
if (connect()) {
return (r.getString("successConnectFTP"));
} else {
return (r.getString("unableToConnectFTP"));
}
}
/**
* <h3>FTP-filelist</h3>
*
* #return String-Array der Dateinamen auf dem FTP-Server
*/
public static String[] list() throws IOException {
FTPClient ftpClient = new FTPClient();
String[] filenameList;
try {
ftpClient.connect(host, port);
ftpClient.login(username, password);
filenameList = ftpClient.listNames();
ftpClient.logout();
} finally {
ftpClient.disconnect();
}
return filenameList;
}
/**
* <h3>FTP-Client-Download:</h3>
*
* #return true falls ok
*/
public static boolean download(String localResultFile,
String remoteSourceFile, boolean showMessages) throws IOException {
FTPClient ftpClient = new FTPClient();
FileOutputStream fos = null;
boolean resultOk = true;
try {
ftpClient.connect(host, port);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
resultOk &= ftpClient.login(username, password);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
fos = new FileOutputStream(localResultFile);
resultOk &= ftpClient.retrieveFile(remoteSourceFile, fos);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
resultOk &= ftpClient.logout();
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {/* nothing to do */
}
ftpClient.disconnect();
}
return resultOk;
}
/**
* <h3>FTP-Client-Upload:</h3>
*
* #param localSourceFile
* The source of local file
* #param remoteResultFile
* Set the destination of the file
* #param showMessages
* If set on TRUE messages will be displayed on the console
* #return true Returns If successfully transfered it will return TRUE, else
* FALSE
*/
public static boolean upload(String localSourceFile,
String remoteResultFile, boolean showMessages) throws IOException {
FTPClient ftpClient = new FTPClient();
FileInputStream fis = null;
boolean resultOk = true;
try {
ftpClient.connect(host, port);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
resultOk &= ftpClient.login(username, password);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
fis = new FileInputStream(localSourceFile);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
resultOk &= ftpClient.storeFile(remoteResultFile, fis);
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
resultOk &= ftpClient.logout();
if (showMessages) {
System.out.println(ftpClient.getReplyString());
}
} finally {
try {
if (fis != null) {
fis.close();
}
ftpClient.disconnect();
} catch (IOException e) {/* nothing to do */
}
}
return resultOk;
}
// Setter and Getter-methods
public static String getHost() {
return host;
}
public static void setHost(String host) {
FtpUpDown.host = host;
}
public static String getUsername() {
return username;
}
public static void setUsername(String username) {
FtpUpDown.username = username;
}
public static int getPort() {
return port;
}
public static void setPort(int port) {
FtpUpDown.port = port;
}
public static String getPassword() {
return password;
}
public static void setPassword(String password) {
FtpUpDown.password = password;
}
}
You create a new connection for every operation, and some code paths don't set the "binary file" flag (i.e. the upload and download methods).
setFileType(FTPClient.BINARY_FILE_TYPE) is the right thing to do, but in the code you provided it is only being done in connect(), which isn't called in download().
Even if it was called in download(), disconnect() is called which ends the session.
Bottom line: You need to call setFileType(FTPClient.BINARY_FILE_TYPE) in the download() method and the upload() method after ftpClient.connect(host, port)

transfer files from unix to windows using java

I want to get a file from unix system to my local system which is on windows using java. I'm very much new to this concept. Any ideas on how it could be done? Which is the best java API for this task?
If the Unix machine supports SFTP, JSch is an option. You could adapt the following code to meet your needs:
private static final String USER_PROMPT = "Enter username#hostname:port";
private static final boolean USE_GUI = true;
public static void main(final String[] arg) {
Session session = null;
ChannelSftp channelSftp = null;
try {
final JSch jsch = new JSch();
final String defaultInput = System.getProperty("user.name") + "#localhost:22";
String input = (USE_GUI) ? JOptionPane.showInputDialog(USER_PROMPT, defaultInput) : System.console().readLine("%s (%s): ", USER_PROMPT, defaultInput);
if (input == null || input.trim().length() == 0) {
input = defaultInput;
}
final int indexOfAt = input.indexOf('#');
final int indexOfColon = input.indexOf(':');
final String user = input.substring(0, indexOfAt);
final String host = input.substring(indexOfAt + 1, indexOfColon);
final int port = Integer.parseInt(input.substring(indexOfColon + 1));
jsch.setKnownHosts("/path/to/known_hosts");
// if you have set up authorized_keys on the server, using that identitiy
// with the code on the next line allows for password-free, trusted connections
// jsch.addIdentity("/path/to/id_rsa", "id_rsa_password");
session = jsch.getSession(user, host, 22);
final UserInfo ui = new MyUserInfo();
session.setUserInfo(ui);
session.connect();
channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
channelSftp.get("/remotepath/remotefile.txt", "/localpath/localfile.txt");
} finally {
if (channelSftp != null) {
channelSftp.exit();
}
if (session != null) {
session.disconnect();
}
}
}
public static class MyUserInfo implements UserInfo {
private String password;
#Override
public String getPassword() {
return password;
}
#Override
public boolean promptYesNo(final String str) {
final Object[] options = {"yes", "no"};
final boolean yesNo = (USE_GUI) ? JOptionPane.showOptionDialog(null, str, "Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]) == 0 : System.console().readLine("Enter y or n: ").equals("y");
return yesNo;
}
#Override
public String getPassphrase() {
return null;
}
#Override
public boolean promptPassphrase(final String message) {
return true;
}
#Override
public boolean promptPassword(final String message) {
if (!USE_GUI) {
password = new String(System.console().readPassword("Password: "));
return true;
} else {
final JTextField passwordField = new JPasswordField(20);
final Object[] ob = {passwordField};
final int result = JOptionPane.showConfirmDialog(null, ob, message, JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
password = passwordField.getText();
return true;
} else {
return false;
}
}
}
#Override
public void showMessage(final String message) {
if (!USE_GUI) {
System.console().printf(message);
} else {
JOptionPane.showMessageDialog(null, message);
}
}
}
I have found JSch to be very useful and straight foreword. Below is a snippet of code written to put all .txt files in a given folder on the sftp server.
public static void sftpConnection() {
// Object Declaration.
JSch jsch = new JSch();
Session session = null;
Channel channel = null;
// Variable Declaration.
String user = "foo";
String host = "10.9.8.7";
Integer port = 22;
String password = "test123";
String watchFolder = "\\localhost\textfiles";
String outputDir = "/remote/textFolder/";
String filemask = "*.txt";
try {
session = jsch.getSession(user, host, port);
/*
* StrictHostKeyChecking Indicates what to do if the server's host
* key changed or the server is unknown. One of yes (refuse connection),
* ask (ask the user whether to add/change the key) and no
* (always insert the new key).
*/
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(password);
session.connect();
channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftpChannel = (ChannelSftp)channel;
// Go through watch folder looking for files.
File[] files = findFile(watchFolder, filemask);
for(File file : files) {
// Upload file.
putFile(file, sftpChannel, outputDir);
}
} finally {
sftpChannel.exit();
session.disconnect();
}
}
public static void putFile(File file, ChannelSftp sftpChannel, String outputDir) {
FileInputStream fis = null;
try {
// Change to output directory.
sftpChannel.cd(outputDir);
// Upload file.
fis = new FileInputStream(file);
sftpChannel.put(fis, file.getName());
fis.close();
} catch{}
}
public static File[] findFile(String dirName, final String mask) {
File dir = new File(dirName);
return dir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String filename)
{ return filename.endsWith(mask); }
} );
}
First thing that goes into my mind is FTP.
There are multiple choices to do that. First one simple socket communication between a java client and a server. If you want to go with this approach then follow this:
http://mrbool.com/file-transfer-between-2-computers-with-java/24516
Then there are other high level protocols implementations that can be used such as FTP, HTTP, etc
Follow a related SO post for java FTP client server: FTP client server model for file transfer in Java

jsch and running "sudo su -"

Using jsch
when i run the following cmd 'sudo su -' the program hangs
[TestNG] Running:
C:\Users\brian.crosby\AppData\Local\Temp\testng-eclipse-952620154\testng-customsuite.xml
[root#tbx2-toy-1 ~]#
It looks like the "sudo su -" worked becasue the output states "[root#tbx2-toy-1 ~]#" but when i send it another cmd it is unresponsive.
heres the code:
package com.linux;
import java.io.InputStream;
import org.testng.annotations.*;
import com.jcraft.jsch.*;
import com.thoughtworks.selenium.*;
public class LinuxConnection extends SeleneseTestBase{
String host = null;
private StringBuilder strFileData;
String randomFileName = null;
public String getFileData() {
return strFileData.toString();
}
public String getRandomFileName() {
return randomFileName;
}
public LinuxConnection() {
strFileData = new StringBuilder();
}
#Test
public void createUpdateTBX2FileData(String command)throws Exception {
try {
JSch jsch = new JSch();
host = "brian-crosby#************.net";
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();
ChannelExec channel = (ChannelExec)session.openChannel("exec");
((ChannelExec)channel).setPty(true);
((ChannelExec) channel).setCommand(command);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
channel.connect();
byte[] tmp = new byte[2048];
while (in.read(tmp, 0, 2048) > 0) {
String str = new String(tmp);
strFileData.append(str);
System.out.println(strFileData);
}
in.close();
channel.disconnect();
session.disconnect();
} catch (Exception e) {
System.out.println(e);
}
}
public static class MyUserInfo implements UserInfo {
public String getPassword() {
return "********";
}
public boolean promptYesNo(String str) {
str = "Yes";
return true;
}
String passwd;
public String getPassphrase() {
return null;
}
public boolean promptPassphrase(String message) {
return true;
}
public boolean promptPassword(String message) {
passwd = "*******";
return true;
}
public void showMessage(String message) {
}
}
}
Here is where i am sending the cmds:
package com.linux;
import org.testng.annotations.*;
public class testLinuxConnection {
#Test
public void testLinux() throws Exception{
LinuxConnection obj = new LinuxConnection();
String command = "touch tester1.txt; sudo su -; rm tester1.txt;";
obj.createUpdateTBX2FileData(command);
}
}
Again i have spent hours on google trying to find a solution but was unsuccessful
Any help is appreciated
You are code is missing the rest of the code needed for this to run. You need to initialize the type of channel you need out of the initialized session object. Since you need to be able to run more than one command after each other, you need a Shell type channel:
You should check JSch's examples (i.e. Shell.java), here it is for a quick reference:
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/**
* This program enables you to connect to sshd server and get the shell prompt.
* $ CLASSPATH=.:../build javac Shell.java
* $ CLASSPATH=.:../build java Shell
* You will be asked username, hostname and passwd.
* If everything works fine, you will get the shell prompt. Output will
* be ugly because of lacks of terminal-emulation, but you can issue commands.
*
*/
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;
public class Shell{
public static void main(String[] arg){
try{
JSch jsch=new JSch();
//jsch.setKnownHosts("/home/foo/.ssh/known_hosts");
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);
String passwd = JOptionPane.showInputDialog("Enter password");
session.setPassword(passwd);
UserInfo ui = new MyUserInfo(){
public void showMessage(String message){
JOptionPane.showMessageDialog(null, message);
}
public boolean promptYesNo(String message){
Object[] options={ "yes", "no" };
int foo=JOptionPane.showOptionDialog(null,
message,
"Warning",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
return foo==0;
}
// If password is not given before the invocation of Session#connect(),
// implement also following methods,
// * UserInfo#getPassword(),
// * UserInfo#promptPassword(String message) and
// * UIKeyboardInteractive#promptKeyboardInteractive()
};
session.setUserInfo(ui);
// It must not be recommended, but if you want to skip host-key check,
// invoke following,
// session.setConfig("StrictHostKeyChecking", "no");
//session.connect();
session.connect(30000); // making a connection with timeout.
Channel channel=session.openChannel("shell");
// Enable agent-forwarding.
//((ChannelShell)channel).setAgentForwarding(true);
channel.setInputStream(System.in);
/*
// a hack for MS-DOS prompt on Windows.
channel.setInputStream(new FilterInputStream(System.in){
public int read(byte[] b, int off, int len)throws IOException{
return in.read(b, off, (len>1024?1024:len));
}
});
*/
channel.setOutputStream(System.out);
/*
// Choose the pty-type "vt102".
((ChannelShell)channel).setPtyType("vt102");
*/
/*
// Set environment variable "LANG" as "ja_JP.eucJP".
((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP");
*/
//channel.connect();
channel.connect(3*1000);
}
catch(Exception e){
System.out.println(e);
}
}
public static abstract class MyUserInfo
implements UserInfo, UIKeyboardInteractive{
public String getPassword(){ return null; }
public boolean promptYesNo(String str){ return false; }
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return false; }
public boolean promptPassword(String message){ return false; }
public void showMessage(String message){ }
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo){
return null;
}
}
}

Capture ssh command output from java

I am trying to run some unix commands from my java code. I am using Google's Expect4J library for now and am open to any well documented libraries out there.
The problem is I am trying to capture output of last run command but am not able to get it. Does anyone know, what I am doing wrong here ?
The problem I am trying to solve here is connect to my jumphost and then SSH to some other servers, based on if I am able to connect, I need to copy or run some scripts on target server.
The code I have written is pasted below. Please help !!!
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.apache.oro.text.regex.MalformedPatternException;
import org.junit.internal.matchers.SubstringMatcher;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.bean.Server;
import expect4j.Closure;
import expect4j.Expect4j;
import expect4j.ExpectState;
import expect4j.matches.Match;
import expect4j.matches.RegExpMatch;
public class ExpectTest1 {
public final String RETURN_CHAR = "\r ";
public String expectOut = "";
private StringBuilder sBuilder = new StringBuilder();
/**
* #param args
*/
public static void main(String[] args) {
Expect4j exp;
List<String> cmdsToRun = new ArrayList<String>();
try {
ExpectTest1 test = new ExpectTest1();
exp = test.SSH("jumpbox.xyz.com","user1","passwd", cmdsToRun);
exp.getLastState().toString();
} catch (Exception e) {
e.printStackTrace();
}
}
public Expect4j SSH(String hostname, String username, String password, List<String> cmdsToRun) throws Exception {
return SSH(hostname, username, password, 22, cmdsToRun);
}
public Expect4j SSH(String hostname, String username, String password, int port, List<String> cmdsToRun) throws Exception {
JSch jsch=new JSch();
Session session=jsch.getSession(username, hostname, port);
if( password != null) {
session.setPassword(password);
}
Hashtable config=new Hashtable();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setDaemonThread(true);
session.connect(3 * 1000); // making a connection with timeout.
ChannelShell channel = (ChannelShell) session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.setPtyType("vt102");
Expect4j expect = new Expect4j(channel.getInputStream(), channel.getOutputStream());
channel.connect(5*1000);
Server hostServer = new Server();
hostServer.setHostName("box1.xyz.com");
hostServer.setUsername("user2");
Server destServer = new Server();
destServer.setHostName("box2.xyz.com");
destServer.setUsername("user3");
boolean isLogged = doSSH(hostServer, expect);
if(isLogged) {
doSSH(destServer, expect);
}
return expect;
}
private boolean doSSH (Server server, Expect4j expect) throws IOException, MalformedPatternException, Exception {
String command = "ssh " + server.getUsername() + "#" + server.getHostName() + RETURN_CHAR;
System.out.println("Logging in to: " + command);
boolean logged;
expect.send(command);
Thread.sleep(4000);
command = "uname -a" + RETURN_CHAR;
System.out.println(command);
expect.send(command);
Thread.sleep(10000);
if(isMatch(expect,server.getHostName().substring(0,server.getHostName().indexOf(".")))) {
System.out.println("Logged in to:" + server.getHostName() + ".....");
return true;
}
if(isMatch(expect, "Last login")) {
System.out.println("Logged in to:" + server.getHostName() + ".....");
return true;
}
if(isMatch(expect, "not known")) {
System.out.println("Node or Service not known...");
return false;
}
System.out.println("Node or Service not known...");
return false;
/*expect.expect(new Match[] {
new RegExpMatch("Name or service not known", new Closure() {
public void run(ExpectState state) throws Exception {
System.out.println("Name or service not known...");
expectOut = state.getBuffer();
}
})
});
expect.expect( new Match[] {
new RegExpMatch("Last login: \\w{3} (.*) from", new Closure() {
public void run(ExpectState state) throws Exception {
System.out.println("Logged In....");
expectOut = state.getBuffer();
}
})
});
if(expectOut != null && expectOut.length()>0 && !expectOut.matches("Name or service not known"))
return true;
return false;*/
}
private boolean isMatch(Expect4j expect, String regEx) throws MalformedPatternException, Exception {
/*expect.expect( new Match[] {
new RegExpMatch(regEx, new Closure() {
public void run(ExpectState state) throws Exception {
System.out.println(state.getBuffer());
System.out.println(state.getMatch());
expectOut = state.getMatch();
//System.out.println(state.getMatch());
}
})
});
if(expectOut != null
&& expectOut.length()>0
&& expectOut.matches(regEx)) {
//System.out.println(regEx);
return true;
}*/
System.out.println("*************");
System.out.println(expect.expect(regEx));
System.out.println("*************");
if(expect.expect(regEx) == 0)
return true;
return false;
}
}
I suspect that your ssh command is trying to prompt for a password or trying to ask you to add the host key to the `known_hosts file. I'm not sure they can be done by Expect4j since ssh connects to the tty directly to ask those questions. But this answer seems to have solved it:
Using expect to pass a password to ssh
Here's a similar question/answers that may help:
How to make a ssh connection to a firewall(router) with java?
When I am automating my ssh connections, I use public/private key encryption instead of passwords to connect to the server and I make sure that the server has been connected from the client from the command line successfully without a password. Make sure that the full host name is used. This will save the host key to the `known_hosts file so it won't be prompted for in the future.
Just an idea, you might consider using a Java library that handles the expect and key management for you. Here is one that I found which seems to do the trick.
http://www.jscape.com/products/components/java/ssh-factory/
See the SshScript or SshSession classes and documentation for details.

Running a Client-Server Chat program

This is one of the most common application scenario that can be found all over the net. and I'm not asking any questions about the java codes that I did because I was successful in running it on my laptop where both the client and server part of the .java file resides. Rather I have had problem getting it to work in between two computers. I tried establishing physical connection using cross-over cable to connect two computers, and did a test to see if file transfers successfully and it did, however, keeping one Server part of the .java file in one computer and client part in the other, I tried to run the server first and then the client but it got a "access denied" error.
For reference here's my two .java files:
/* ChatClient.java */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class ChatClient {
private static int port = 5000; /* port to connect to */
private static String host = "localhost"; /* host to connect to (server's IP)*/
private static BufferedReader stdIn;
private static String nick;
/**
* Read in a nickname from stdin and attempt to authenticate with the
* server by sending a NICK command to #out. If the response from #in
* is not equal to "OK" go bacl and read a nickname again
*/
private static String getNick(BufferedReader in,
PrintWriter out) throws IOException {
System.out.print("Enter your nick: ");
String msg = stdIn.readLine();
out.println("NICK " + msg);
String serverResponse = in.readLine();
if ("SERVER: OK".equals(serverResponse)) return msg;
System.out.println(serverResponse);
return getNick(in, out);
}
public static void main (String[] args) throws IOException {
Socket server = null;
try {
server = new Socket(host, port);
} catch (UnknownHostException e) {
System.err.println(e);
System.exit(1);
}
stdIn = new BufferedReader(new InputStreamReader(System.in));
/* obtain an output stream to the server... */
PrintWriter out = new PrintWriter(server.getOutputStream(), true);
/* ... and an input stream */
BufferedReader in = new BufferedReader(new InputStreamReader(
server.getInputStream()));
nick = getNick(in, out);
/* create a thread to asyncronously read messages from the server */
ServerConn sc = new ServerConn(server);
Thread t = new Thread(sc);
t.start();
String msg;
/* loop reading messages from stdin and sending them to the server */
while ((msg = stdIn.readLine()) != null) {
out.println(msg);
}
}
}
class ServerConn implements Runnable {
private BufferedReader in = null;
public ServerConn(Socket server) throws IOException {
/* obtain an input stream from the server */
in = new BufferedReader(new InputStreamReader(
server.getInputStream()));
}
public void run() {
String msg;
try {
/* loop reading messages from the server and show them
* on stdout */
while ((msg = in.readLine()) != null) {
System.out.println(msg);
}
} catch (IOException e) {
System.err.println(e);
}
}
}
and here's the ChatServer.java:
/* ChatServer.java */
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Hashtable;
public class ChatServer {
private static int port = 5000; /* port to listen on */
public static void main (String[] args) throws IOException
{
ServerSocket server = null;
try {
server = new ServerSocket(port); /* start listening on the port */
} catch (IOException e) {
System.err.println("Could not listen on port: " + port);
System.err.println(e);
System.exit(1);
}
Socket client = null;
while(true) {
try {
client = server.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.err.println(e);
System.exit(1);
}
/* start a new thread to handle this client */
Thread t = new Thread(new ClientConn(client));
t.start();
}
}
}
class ChatServerProtocol {
private String nick;
private ClientConn conn;
/* a hash table from user nicks to the corresponding connections */
private static Hashtable<String, ClientConn> nicks =
new Hashtable<String, ClientConn>();
private static final String msg_OK = "OK";
private static final String msg_NICK_IN_USE = "NICK IN USE";
private static final String msg_SPECIFY_NICK = "SPECIFY NICK";
private static final String msg_INVALID = "INVALID COMMAND";
private static final String msg_SEND_FAILED = "FAILED TO SEND";
/**
* Adds a nick to the hash table
* returns false if the nick is already in the table, true otherwise
*/
private static boolean add_nick(String nick, ClientConn c) {
if (nicks.containsKey(nick)) {
return false;
} else {
nicks.put(nick, c);
return true;
}
}
public ChatServerProtocol(ClientConn c) {
nick = null;
conn = c;
}
private void log(String msg) {
System.err.println(msg);
}
public boolean isAuthenticated() {
return ! (nick == null);
}
/**
* Implements the authentication protocol.
* This consists of checking that the message starts with the NICK command
* and that the nick following it is not already in use.
* returns:
* msg_OK if authenticated
* msg_NICK_IN_USE if the specified nick is already in use
* msg_SPECIFY_NICK if the message does not start with the NICK command
*/
private String authenticate(String msg) {
if(msg.startsWith("NICK")) {
String tryNick = msg.substring(5);
if(add_nick(tryNick, this.conn)) {
log("Nick " + tryNick + " joined.");
this.nick = tryNick;
return msg_OK;
} else {
return msg_NICK_IN_USE;
}
} else {
return msg_SPECIFY_NICK;
}
}
/**
* Send a message to another user.
* #recepient contains the recepient's nick
* #msg contains the message to send
* return true if the nick is registered in the hash, false otherwise
*/
private boolean sendMsg(String recipient, String msg) {
if (nicks.containsKey(recipient)) {
ClientConn c = nicks.get(recipient);
c.sendMsg(nick + ": " + msg);
return true;
} else {
return false;
}
}
/**
* Process a message coming from the client
*/
public String process(String msg) {
if (!isAuthenticated())
return authenticate(msg);
String[] msg_parts = msg.split(" ", 3);
String msg_type = msg_parts[0];
if(msg_type.equals("MSG")) {
if(msg_parts.length < 3) return msg_INVALID;
if(sendMsg(msg_parts[1], msg_parts[2])) return msg_OK;
else return msg_SEND_FAILED;
} else {
return msg_INVALID;
}
}
}
class ClientConn implements Runnable {
private Socket client;
private BufferedReader in = null;
private PrintWriter out = null;
ClientConn(Socket client) {
this.client = client;
try {
/* obtain an input stream to this client ... */
in = new BufferedReader(new InputStreamReader(
client.getInputStream()));
/* ... and an output stream to the same client */
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.err.println(e);
return;
}
}
public void run() {
String msg, response;
ChatServerProtocol protocol = new ChatServerProtocol(this);
try {
/* loop reading lines from the client which are processed
* according to our protocol and the resulting response is
* sent back to the client */
while ((msg = in.readLine()) != null) {
response = protocol.process(msg);
out.println("SERVER: " + response);
}
} catch (IOException e) {
System.err.println(e);
}
}
public void sendMsg(String msg) {
out.println(msg);
}
}
Now, what should I do in order to run this two files from two computers given that I have the physical connection(TCP/IP) setup already??
Thanks in advance... :)
Sounds like it's quite possibly a firewall problem. Have you tried opening a hole in your firewall for port 1001?
Have you also looked at your java.policy and make sure that it is configured to allow local codebase to open sockets?
as mentioned in comment, you should not use port < 1025 for you applications, since they are always used in deamon processes. However you should test your program like this
1) if you get connection refused then you should check the exception properly, whether client program takes time before generating exception ( that mean request is going to server and then it's giving connection refused), in that case you should try java.policy put following in a file named java.policy
grant {
permission java.net.SocketPermission ":1024-65535",
"connect,accept";
permission java.net.SocketPermission ":80", "connect";
permission java.io.FilePermission "", "read,write,delete";
permission java.security.SecurityPermission "";
};
while compiling use this flag -Djava.security.policy=java.policy
more-over you should also try -Djava.rmi.server.hostname=IP, where IP is clien-ip for client.java and server-ip for server.java
2) if you are immediately getting exception at client side then your request is not going outside your pc, so client has some problem.
check the exception properly and post them over here.
3) though i've not got access denied error, but it seems to have port problem that might be solved using policy or port>1024.
post what are you getting now.

Categories

Resources