I am trying to connect Linux from windows using Java. Given below is the code which I have used for this process. The actual issue I am facing during session.connect() .i.e. it is prompting for Kerberos username which I have tried to enter username and password using command exec but I am not able to succeed.
I cannot skip Kerberos authentication also since this authentication is required to perform any batch operations.
Please assist me in connecting Linux by entering Kerberos username and password in an automated way.
Java code:
import com.jcraft.jsch.*;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class SSHClient {
public static void main(String[] args) throws JSchException, IOException {
String endLineStr = " # "; // it is dependant to the server
String host = ""; // host IP
String user = ""; // username for SSH connection
String password = ""; // password for SSH connection
int port = 22; // default SSH port
JSch shell = new JSch();
// get a new session
Session session = shell.getSession(user, host, port);
// set user password and connect to a channel
session.setUserInfo(new SSHUserInfo(password));
session.connect();
Channel channel = session.openChannel("shell");
channel.connect();
ChannelExec channelExec = (ChannelExec)session.openChannel("exec");
InputStream in = channelExec.getInputStream();
channelExec.setCommand("ls");
channelExec.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
int index = 0;
while ((line = reader.readLine()) != null)
{
System.out.println(++index + " : " + line);
}
int exitStatus = channelExec.getExitStatus();
channelExec.disconnect();
session.disconnect();
if(exitStatus < 0){
System.out.println("Done, but exit status not set!");
}
else if(exitStatus > 0){
System.out.println("Done, but with error!");
}
else{
System.out.println("Done!");
}
// DataInputStream dataIn = new DataInputStream(channel.getInputStream());
// DataOutputStream dataOut = new DataOutputStream(channel.getOutputStream());
//
// // send ls command to the server
// dataOut.writeBytes("ls");
// dataOut.flush();
//
// // and print the response
// String line = dataIn.readLine();
// System.out.println(line);
// while(!line.endsWith(endLineStr)) {
// System.out.println(line);
// line = dataIn.readLine();
// }
// dataIn.close();
// dataOut.close();
channel.disconnect();
session.disconnect();
}
// this class implements jsch UserInfo interface for passing password to the session
static class SSHUserInfo implements UserInfo {
private String password;
SSHUserInfo(String password) {
this.password = password;
}
public String getPassphrase() {
return null;
}
public String getPassword() {
return password;
}
public boolean promptPassword(String arg0) {
return true;
}
public boolean promptPassphrase(String arg0) {
return true;
}
public boolean promptYesNo(String arg0) {
return true;
}
public void showMessage(String arg0) {
System.out.println(arg0);
}
}
}
Related
I have a task:
to do telnet commands through ssh session.
I have read similar problems:
Running telnet command on remote SSH session using JSch
telnet through SSH
Execution hangs after Running telnet command on remote SSH session using JSch
And I wrote the code (with lib https://mvnrepository.com/artifact/com.jcraft/jsch):
Class Ssh:
public class Ssh {
private final String USER;
private final String PASSWORD;
private final String HOST;
public Ssh(String user, String password, String host) {
this.USER = user;
this.PASSWORD = password;
this.HOST = host;
}
public Session runSsh() {
try {
Session session = new JSch().getSession(USER, HOST, 22);
session.setPassword(PASSWORD);
// It must not be recommended, but if you want to skip host-key check,
session.setConfig("StrictHostKeyChecking", "no");
session.connect(3000);
return session;
} catch (JSchException e) {
System.out.println(e);
}
return null;
}
}
Class Telnet
public class Telnet {
public String runCommand(Session session, String command) throws Exception {
Channel channel = session.openChannel("shell");
channel.connect(3000);
DataOutputStream outputStream = new DataOutputStream(channel.getOutputStream());
outputStream.writeBytes("telnet localhost 5000\r\n");
outputStream.writeBytes(command + "\r\n");
outputStream.writeBytes("exit\r\n");
outputStream.flush();
DataInputStream inputStream = new DataInputStream(channel.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
channel.setInputStream(inputStream, true);
String line = reader.readLine();
String result = line +"\n";
while (!(line= reader.readLine()).equals("exit")){
result += line +"\n";
}
result += "Connection closed by foreign host";
outputStream.close();
inputStream.close();
channel.disconnect();
session.disconnect();
return result;
}
}
Class Main
public class Main {
public static void main(String[] arg) {
Ssh ssh = new Ssh("user","password","ip-server");
Telnet telnet = new Telnet();
try {
Session sessionSsh = ssh.runSsh();
String result = telnet.runCommand(sessionSsh, "H");
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I get the result:
telnet localhost 5000
Entering character mode
Escape character is '^]'.
Command Shell 1 on intelpc-1 (Port: 5000)
b01_1_1 (5000) >
H
Connection closed by foreign host
Process finished with exit code 0
I don't see the result of executing the command telnet...
I made different commands via telnet:
- H
or
- u s3
But I can't see their result :(
Tell me please. How do I get the results of the telnet command execution?
I debugged your example and in my case, I needed to wait for the program, which you connect via telnet, until it is ready to receive a command.
In the second step, you can send your command and the exit command to stop the telnet, so you are reading from the stream until it has stopped by saying "Connection closed...". Be aware, that exiting from telnet can have different commands, some use quit, some other use exit or only wait for a termination signal.
class Telnet {
public String runCommand(Session session, String command) throws Exception {
Channel channel = session.openChannel("shell");
channel.connect(3000);
DataOutputStream outputStream = new DataOutputStream(channel.getOutputStream());
outputStream.writeBytes("telnet localhost 16379\r\n");
outputStream.flush();
DataInputStream inputStream = new DataInputStream(channel.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
channel.setInputStream(inputStream, true);
// Read until we are ready to write
String line;
while (!(line= reader.readLine()).equals("Escape character is '^]'.")){
System.out.println(line);
}
// write command and exit telnet
outputStream.writeBytes(command + "\r\n");
outputStream.writeBytes("quit\r\n");
outputStream.flush();
// read until telnet has closed
String result = "";
while (!(line= reader.readLine()).equals("Connection closed by foreign host.")){
result += line +"\n";
}
outputStream.close();
inputStream.close();
channel.disconnect();
session.disconnect();
return result;
}
}
In the end, there are alternative ways to communicate without telnet, i.e. local port forwarding.
Thanks to Matthias Wiedemann.
I used the SSH tunneling https://www.ssh.com/academy/ssh/tunneling/example as Matthias Wiedemann advised.
Total:
1 step. Connecting via SSH and create session SSH
SSH ssh = new SSH(user, password, host, port);
Session session = SSHUtil.createSession(ssh);
2 step. Creating a tunnel using SSH
SSHUtil.createChannel(session, outputConsole);
SSHUtil.createSshTunnel(session, port);
3 step. Connection via Telnet and executing Telnet commands using the tunnel port (instead of 5000, the port became 9999).
clientForTelnet = new ClientForTelnet(new Telnet(host, port));
outputConsole.print(TelnetUtil.connect(clientForTelnet));
outputConsole is PrintStream.
I got the following:
1.
public class SSHUtil{
private final static Logger LOGGER = LogManager.getLogger(SSHUtil.class);
public static Session createSession(SSH ssh) {
Session session = null;
try {
session = new JSch().getSession(ssh.getUSER(), ssh.getHOST().getIp(), ssh.getPORT().getPort());
session.setPassword(ssh.getPASSWORD());
session.setConfig("StrictHostKeyChecking", "no"); // It must not be recommended, but if you want to skip host-key check
session.connect(10000);
LOGGER.info("SSH session created");
} catch (JSchException e) {
LOGGER.error("SSH session not created " + e);
}
return session;
}
public static Channel createChannel(Session session, PrintStream output) {
Channel channel = null;
try {
channel = session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(output);
// streamOut = channel.getOutputStream();
channel.connect(10000);
LOGGER.info("SSH channel created");
} catch (JSchException e) {
LOGGER.error("SSH channel not created " + e);
}
return channel;
}
public static void createSshTunnel(Session session, Port port) {
// TODO сделать пул портов, чтобы исключить вероятность, что порт 9999 занят
try {
session.setPortForwardingL(9999, session.getHost(), port.getPort());
LOGGER.info("Tunnel created localhost:" + 9999 + " -> " + session.getHost() + ":" + port.getPort());
} catch (JSchException e) {
LOGGER.error("SSH tunnel not created " + e);
}
}
public static void disconnect(Session session) {
if (session != null && session.isConnected()) {
session.disconnect();
}
}
}
public class TelnetUtil {
private final static Logger LOGGER = LogManager.getLogger(TelnetUtil.class);
public static String connect(ClientForTelnet clientForTelnet) {
try {
// Connect to the server
clientForTelnet.getTc().connect(clientForTelnet.getTelnet().getHOST().getIp(), clientForTelnet.getTelnet().getPORT().getPort());
// Get input and output stream references
clientForTelnet.setIn(clientForTelnet.getTc().getInputStream());
clientForTelnet.setOut(new PrintStream(clientForTelnet.getTc().getOutputStream()));
} catch (IOException e) {
LOGGER.error(e);
}
return readUntil(clientForTelnet.getPrompt(), clientForTelnet.getIn());
}
public static String readUntil(String pattern, InputStream in) {
StringBuilder sb = new StringBuilder();
try {
char lastChar = pattern.charAt(pattern.length() - 1);
boolean found = false;
char ch = (char) in.read();
while (true) {
// System.out.print(ch);
sb.append(ch);
if (ch == lastChar) {
if (sb.toString().endsWith(pattern)) {
return sb.toString();
}
}
ch = (char) in.read();
}
} catch (IOException e) {
LOGGER.error(e);
}
return sb.toString();
}
public static void write(String value, PrintStream out) {
out.println(value);
out.flush();
}
public static String sendCommand(ClientForTelnet clientForTelnet, String command) {
write(command, clientForTelnet.getOut());
return readUntil(clientForTelnet.getPrompt(), clientForTelnet.getIn());
}
public static void disconnect(TelnetClient tc) {
try {
tc.disconnect();
} catch (IOException e) {
LOGGER.error(e);
}
}
}
public class SSH {
private final String USER;
private final String PASSWORD;
private final Host HOST;
private final Port PORT;
private final Port DEFAULT_PORT = new Port(22);
public SSH(String user, String password, Host host, Port port) {
this.USER = user;
this.PASSWORD = password;
this.HOST = host;
this.PORT = port;
}
public SSH(String user, String password, Host host) {
this.USER = user;
this.PASSWORD = password;
this.HOST = host;
this.PORT = DEFAULT_PORT;
}
public String getUSER() {
return USER;
}
public String getPASSWORD() {
return PASSWORD;
}
public Host getHOST() {
return HOST;
}
public Port getPORT() {
return PORT;
}
}
public class Telnet {
private final Host HOST;
private final Port PORT;
private final Port DEFAULT_PORT = new Port(5000);
public Telnet(Host host, Port port) {
this.HOST = host;
this.PORT = port;
}
public Telnet(Host host) {
this.HOST = host;
this.PORT = DEFAULT_PORT;
}
public Host getHOST() {
return HOST;
}
public Port getPORT() {
return PORT;
}
}
public class ClientForTelnet {
private final TelnetClient TC = new TelnetClient();
private final String PROMT = ">";
private final Telnet TELNET;
private InputStream in;
private PrintStream out;
public ClientForTelnet(Telnet telnet) {
this.TELNET = telnet;
}
public InputStream getIn() {
return in;
}
public PrintStream getOut() {
return out;
}
public Telnet getTelnet() {
return TELNET;
}
public String getPrompt() {
return PROMT;
}
public TelnetClient getTc() {
return TC;
}
public void setIn(InputStream in) {
this.in = in;
}
public void setOut(PrintStream out) {
this.out = out;
}
}
public class Host {
private final static Logger LOGGER = LogManager.getLogger(Host.class);
private String ip;
public Host(String ip) {
this.ip = ip;
}
public String getIp() {
return ip;
}
}
I am using a JSCH -SSH library to execute command in "shell" channel, but unable to find a way
to do 2 things:-
1) How to find whether the command is completely executed on remote unix box ?
2) How to capture the command output in String , instead of printing it on System.out console ?
Below is my code snippet which works fine to display shell command output on system.out
NOTE :I do NOT want to use ,"exec" channel, as it starts a new process for each command and does not remember "session" variables which were exported. I must use "shell" channel.
Below is my code snippet. Any help is appreciated.Thanks for your time.
try{
String commandToRun = "ls /tmp/*.log \n";
if(channel.isClosed())
channel=session.openChannel("shell");
byte[] bytes = commandToRun.getBytes();
ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
channel.setInputStream(bais);
InputStream ins=channel.getInputStream();
channel.connect();
channel.setOutputStream(System.out);//This prints on console. Need 2 capture in String somehow?
//in-efficient way to allow command to execute completely on remote Unix machine
//DO NOT know a better way, to know when command is executed completely
Thread.sleep(5000L);
}
catch(Exception e){
System.out.println("Exception in executeCommand() --->"+ e.getMessage());
e.printStackTrace();
}
My solution may not be needed anymore for the OP, but anyone else who is searching for a solution to cover both conditions 1) waiting for the commands to finish on remote machine; and 2) capturing output as string; you can try this:
public class SshConnectionManager {
private static Session session;
private static ChannelShell channel;
private static String username = "";
private static String password = "";
private static String hostname = "";
private static Session getSession(){
if(session == null || !session.isConnected()){
session = connect(hostname,username,password);
}
return session;
}
private static Channel getChannel(){
if(channel == null || !channel.isConnected()){
try{
channel = (ChannelShell)getSession().openChannel("shell");
channel.connect();
}catch(Exception e){
System.out.println("Error while opening channel: "+ e);
}
}
return channel;
}
private static Session connect(String hostname, String username, String password){
JSch jSch = new JSch();
try {
session = jSch.getSession(username, hostname, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!");
}catch(Exception e){
System.out.println("An error occurred while connecting to "+hostname+": "+e);
}
return session;
}
private static void executeCommands(List<String> commands){
try{
Channel channel=getChannel();
System.out.println("Sending commands...");
sendCommands(channel, commands);
readChannelOutput(channel);
System.out.println("Finished sending commands!");
}catch(Exception e){
System.out.println("An error ocurred during executeCommands: "+e);
}
}
private static void sendCommands(Channel channel, List<String> commands){
try{
PrintStream out = new PrintStream(channel.getOutputStream());
out.println("#!/bin/bash");
for(String command : commands){
out.println(command);
}
out.println("exit");
out.flush();
}catch(Exception e){
System.out.println("Error while sending commands: "+ e);
}
}
private static void readChannelOutput(Channel channel){
byte[] buffer = new byte[1024];
try{
InputStream in = channel.getInputStream();
String line = "";
while (true){
while (in.available() > 0) {
int i = in.read(buffer, 0, 1024);
if (i < 0) {
break;
}
line = new String(buffer, 0, i);
System.out.println(line);
}
if(line.contains("logout")){
break;
}
if (channel.isClosed()){
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee){}
}
}catch(Exception e){
System.out.println("Error while reading channel output: "+ e);
}
}
public static void close(){
channel.disconnect();
session.disconnect();
System.out.println("Disconnected channel and session");
}
public static void main(String[] args){
List<String> commands = new ArrayList<String>();
commands.add("ls -l");
executeCommands(commands);
close();
}
}
This solution is also useful if you need to send multiple commands at a time and keep the channel open to reuse it later.
For 2) u can use ByteArrayOutputStream
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
channel.setOutputStream(baos);
and then create new string from new String(baos.toByteArray())
For 1 have you tried to use 2>&1 at the end of your command?
String commandToRun = "ls /tmp/*.log 2>&1 \n";
Taking the example provided by Mihail, other info on the internets, and the feedback from Martin, here's a reworked solution using exec. Note that opening a session allows multiple commands to be sent, each one opening it's own channel for input/output.
Rant:I really dislike having to get the process' OUTPUT stream to write to. What an annoying paradigm (at least for me). What I wanted is the processes input stream to write my output to, and had an amazingly difficult time working out that it's inverted. Is it just me or does the following (pseudocode) not make way more sense??
channel.getInputStream().write("here's some text to write into my channel.");
String ret = channel.getOutputStream().getOutput();
Anyways, thanks to Mihail and Martin for their comments / input.
public class SSHConnectionManager {
private Session session;
private String username = "user";
private String password = "password";
private String hostname = "myhost";
public SSHConnectionManager() { }
public SSHConnectionManager(String hostname, String username, String password) {
this.hostname = hostname;
this.username = username;
this.password = password;
}
public void open() throws JSchException {
open(this.hostname, this.username, this.password);
}
public void open(String hostname, String username, String password) throws JSchException{
JSch jSch = new JSch();
session = jSch.getSession(username, hostname, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no"); // not recommended
session.setConfig(config);
session.setPassword(password);
System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
session.connect();
System.out.println("Connected!");
}
public String runCommand(String command) throws JSchException, IOException {
String ret = "";
if (!session.isConnected())
throw new RuntimeException("Not connected to an open session. Call open() first!");
ChannelExec channel = null;
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
channel.setInputStream(null);
PrintStream out = new PrintStream(channel.getOutputStream());
InputStream in = channel.getInputStream(); // channel.getInputStream();
channel.connect();
// you can also send input to your running process like so:
// String someInputToProcess = "something";
// out.println(someInputToProcess);
// out.flush();
ret = getChannelOutput(channel, in);
channel.disconnect();
System.out.println("Finished sending commands!");
return ret;
}
private String getChannelOutput(Channel channel, InputStream in) throws IOException{
byte[] buffer = new byte[1024];
StringBuilder strBuilder = new StringBuilder();
String line = "";
while (true){
while (in.available() > 0) {
int i = in.read(buffer, 0, 1024);
if (i < 0) {
break;
}
strBuilder.append(new String(buffer, 0, i));
System.out.println(line);
}
if(line.contains("logout")){
break;
}
if (channel.isClosed()){
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee){}
}
return strBuilder.toString();
}
public void close(){
session.disconnect();
System.out.println("Disconnected channel and session");
}
public static void main(String[] args){
SSHConnectionManager ssh = new SSHConnectionManager();
try {
ssh.open();
String ret = ssh.runCommand("ls -l");
System.out.println(ret);
ssh.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I have a test case which connects to my app server using Jsch shell channel. I am able to execute commands using Jsch if I run my test case from test vm. But there is some situation that the test case will run in the app server and do ssh to itself with same credentials. My problem is here. In this case the commands are not executed by Jsch.
Code:
import com.google.common.io.Files;
import com.jcraft.jsch.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.*;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Properties;
/**
* Created by prasantabiswas on 17/03/17.
*/
public class SSHManager
{
private static Session session;
private static Channel channel;
private static ChannelSftp channelSftp;
private static Logger log= LogManager.getLogger(SSHManager.class);
private static HelperClass helperClass=HelperClass.getInstance();
enum ChannelType
{
SHELL,
SFTP
}
public static void openConnection(String remoteHost) throws JSchException,SecurityException
{
if(session == null || !session.isConnected())
{
String userName=helperClass.getSshUser();
log.debug("Remote host: "+remoteHost);
log.debug("SSH user: "+userName);
if(helperClass.getSshAuthMode().equalsIgnoreCase("key"))
{
String key=helperClass.getSshKey();
log.debug("SSH key: "+key);
session=connectWithKey(remoteHost,userName,key);
}
else if(helperClass.getSshAuthMode().equalsIgnoreCase("password"))
{
String password=helperClass.getSshPassword();
log.debug("SSH password: "+password);
session=connectWithPassword(remoteHost,userName,password);
}
else
{
String password=helperClass.getSshPassword();
log.warn("No SSH authentication mode provided. It will try with the default mode that is with password: "+password);
session=connectWithPassword(remoteHost,userName,password);
}
}
else
log.warn("Session already connected. Disconnect first for new session.");
}
private static Session connectWithPassword(String hostname,String username,String password) throws JSchException,SecurityException
{
JSch jSch = new JSch();
Session _session = jSch.getSession(username, hostname, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
_session.setConfig(config);
_session.setPassword(password);
log.info("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
_session.connect();
log.info("Connected!");
return _session;
}
private static Session connectWithKey(String hostname,String username,String key) throws JSchException,SecurityException
{
JSch jSch = new JSch();
log.debug("Key file path: "+key);
jSch.addIdentity(key);
Session _session = jSch.getSession(username, hostname, 22);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
_session.setConfig(config);
log.info("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
_session.connect();
log.info("Connected!");
return _session;
}
private static void createChannel(ChannelType channelType)
{
if(channel == null || !channel.isConnected()){
try
{
if(channelType==ChannelType.SHELL)
{
channel = session.openChannel("shell");
log.info("Shell channel created!");
}
else if(channelType==ChannelType.SFTP)
{
channel = session.openChannel("sftp");
log.info("SFTP channel created!");
}
else
throw new JSchException("Invalid channel type");
channel.connect();
}
catch(JSchException e)
{
log.error("Error while opening channel: "+ e);
}
}
}
public static String executeCommand(List<String> commands,String remoteHost) throws JSchException,IOException
{
log.info("Opening SSH session...");
openConnection(remoteHost);
log.info("Creating shell channel...");
createChannel(ChannelType.SHELL);
log.info("Sending commands...");
PrintStream out = new PrintStream(channel.getOutputStream());
out.println("#!/bin/bash");
for(String command : commands){
out.println(command);
}
out.println("exit");
out.flush();
String output=getChannelOutput(channel);
log.info("Finished sending commands!");
log.info("Closing session...");
close();
log.info("Returning execution output...");
return output;
}
public static void copyFileToRemoteHost(String sourcePath,String destinationPath,String remoteHost) throws SftpException, IOException, JSchException
{
log.info("Opening SSH session...");
openConnection(remoteHost);
log.info("Creating SFTP channel...");
createChannel(ChannelType.SFTP);
log.info("Copying file to remote host: "+remoteHost+" from "+sourcePath+" to "+destinationPath);
channelSftp = (ChannelSftp) channel;
channelSftp.cd(destinationPath);
File sourceFile = new File(sourcePath);
channelSftp.put(new FileInputStream(sourceFile), sourceFile.getName(),channelSftp.OVERWRITE);
log.info("File transfer complete.");
log.info("Closing session...");
close();
}
public static void removeFileFromRemoteHost(String targetPath,String remoteHost) throws JSchException, SftpException, IOException
{
log.info("Opening SSH session...");
openConnection(remoteHost);
log.info("Creating SFTP channel...");
createChannel(ChannelType.SFTP);
log.info("Removing file from remote host: "+remoteHost+" at "+targetPath);
channelSftp = (ChannelSftp) channel;
channelSftp.rm(targetPath);
log.info("File removed");
log.info("Closing session...");
close();
}
private static String getChannelOutput(Channel channel) throws IOException
{
byte[] buffer = new byte[1024];
InputStream in = channel.getInputStream();
String line = "";
Calendar calendar= Calendar.getInstance();
calendar.setTime(new Date());
int minuteBefore=calendar.get(Calendar.MINUTE);
int minuteAfter=0;
while (true)
{
while (in.available() > 0)
{
int i = in.read(buffer, 0, 1024);
if (i < 0)
{
break;
}
line += "\n" + new String(buffer, 0, i);
}
if(line.contains("logout"))
{
break;
}
if (channel.isClosed())
{
break;
}
calendar.setTime(new Date());
minuteAfter=calendar.get(Calendar.MINUTE);
if(minuteAfter-minuteBefore>=3)
break;
try
{
Thread.sleep(1000);
} catch (Exception e)
{
}
}
return line;
}
public static void close()
{
channel.disconnect();
session.disconnect();
log.info("Disconnected channel and session");
}
}
I am using the above class to execute commands on remote host. This is working fine but when I am running it in my local machine with the remoteHost parameter being the localhost, the commands are not getting executed. However it successfully logs in which I can see in the log but cannot execute the commands which are sent throug print stream. It is stuck for sometime after "Sending commands..." and then return the log which only shows the command prompt not all the commands.
Suppose my ssh username is root and I am sending two commands : su - admin, txe restart and the remote host and the host I am running the test is same that is my localhost. I should get output like
#!/bin/bash
su - admin
txe restart
exit
Last login: Thu Apr 13 23:17:10 2017 from 10.10.4.46
[root#platform15 ~]# #!/bin/bash
[root#platform15 ~]# su - admin
id: cannot find name for group ID 491000000
admin#platform15(ERS):~> txe restart
Stopping txe...
.
.
OK
Starting txe...OK (PID: 13083)
admin#platform15(ERS):~> exit
logout
But I get this
Last login: Thu Apr 13 23:34:42 2017 from 10.10.4.27
[root#platform15 ~]#
This is only happening when I am running the test in localhost with remoteHost set to localhost. Otherwise it is working fine is remoteHost is set to some other host.
Any suggestion on this?
I found a socket SMTP client example slightly modified for it to connect to gmail using SSLsockets, but now I don't know how to authorise account, that I am sending from. (I don't use JAVAMAIL, because this is homework)
public class SMTP {
public static void main(String args[]) throws IOException,
UnknownHostException {
String msgFile = "file.txt";
String from = "from#gmail.com";
String to = "to#gmail.com";
String mailHost = "smtp.gmail.com";
SMTP mail = new SMTP(mailHost);
if (mail != null) {
if (mail.send(new FileReader(msgFile), from, to)) {
System.out.println("Mail sent.");
} else {
System.out.println("Connect to SMTP server failed!");
}
}
System.out.println("Done.");
}
static class SMTP {
private final static int SMTP_PORT = 25;
InetAddress mailHost;
InetAddress localhost;
BufferedReader in;
PrintWriter out;
public SMTP(String host) throws UnknownHostException {
mailHost = InetAddress.getByName(host);
localhost = InetAddress.getLocalHost();
System.out.println("mailhost = " + mailHost);
System.out.println("localhost= " + localhost);
System.out.println("SMTP constructor done\n");
}
public boolean send(FileReader msgFileReader, String from, String to)
throws IOException {
SSLSocket smtpPipe;
InputStream inn;
OutputStream outt;
BufferedReader msg;
msg = new BufferedReader(msgFileReader);
smtpPipe = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(InetAddress.getByName("smtp.gmail.com"), 465);
if (smtpPipe == null) {
return false;
}
inn = smtpPipe.getInputStream();
outt = smtpPipe.getOutputStream();
in = new BufferedReader(new InputStreamReader(inn));
out = new PrintWriter(new OutputStreamWriter(outt), true);
if (inn == null || outt == null) {
System.out.println("Failed to open streams to socket.");
return false;
}
String initialID = in.readLine();
System.out.println(initialID);
System.out.println("HELO " + localhost.getHostName());
out.println("HELO " + localhost.getHostName());
String welcome = in.readLine();
System.out.println(welcome);
System.out.println("MAIL From:<" + from + ">");
out.println("MAIL From:<" + from + ">");
String senderOK = in.readLine();
System.out.println(senderOK);
System.out.println("RCPT TO:<" + to + ">");
out.println("RCPT TO:<" + to + ">");
String recipientOK = in.readLine();
System.out.println(recipientOK);
System.out.println("DATA");
out.println("DATA");
String line;
while ((line = msg.readLine()) != null) {
out.println(line);
}
System.out.println(".");
out.println(".");
String acceptedOK = in.readLine();
System.out.println(acceptedOK);
System.out.println("QUIT");
out.println("QUIT");
return true;
}
}
}
Rewrote the code. This works fine.
public class TotalTemp
{
private static DataOutputStream dos;
public static void main(String[] args) throws Exception
{
int delay = 1000;
String user = "xxxxx#gmail.com";
String pass = "xxxxxxxx11";
String username = Base64.encodeBase64String(user.getBytes(StandardCharsets.UTF_8));
String password = Base64.encodeBase64String(pass.getBytes(StandardCharsets.UTF_8));
SSLSocket sock = (SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket("smtp.gmail.com", 465);
// Socket sock = new Socket("smtp.gmail.com", 587);
final BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
(new Thread(new Runnable()
{
public void run()
{
try
{
String line;
while((line = br.readLine()) != null)
System.out.println("SERVER: "+line);
}
catch (IOException e)
{
e.printStackTrace();
}
}
})).start();
dos = new DataOutputStream(sock.getOutputStream());
send("EHLO smtp.gmail.com\r\n");
Thread.sleep(delay);
send("AUTH LOGIN\r\n");
Thread.sleep(delay);
send(username + "\r\n");
Thread.sleep(delay);
send(password + "\r\n");
Thread.sleep(delay);
send("MAIL FROM:<XXXXXXXX#gmail.com>\r\n");
//send("\r\n");
Thread.sleep(delay);
send("RCPT TO:<YYYYYYYY#gmail.com>\r\n");
Thread.sleep(delay);
send("DATA\r\n");
Thread.sleep(delay);
send("Subject: Email test\r\n");
Thread.sleep(delay);
send("Test 1 2 3\r\n");
Thread.sleep(delay);
send(".\r\n");
Thread.sleep(delay);
send("QUIT\r\n");
}
private static void send(String s) throws Exception
{
dos.writeBytes(s);
System.out.println("CLIENT: "+s);
}
}
First, Make sure you have turned on 'Allow Less Secure Apps' from your Gmail.
We can improve the code by ignoring the Multi-threading part by just reading the output from server. As we know from the RFC that server sends 9 lines after getting the first 'EHLO' request. So, we are just reading 9 lines with bufferedReader. Then for the next few commands, it returns only one line. So, the simplified code without multithreading will be like this :
import java.nio.charset.StandardCharsets;
import javax.net.ssl.*;
import java.io.*;
import java.util.Base64;
public class SMTP_Simplified_v2 {
// Credentials
public static String user = "xxxxxxx#gmail.com";
public static String pass = "xxxxxxxxxx";
private static DataOutputStream dataOutputStream;
public static BufferedReader br = null;
public static void main(String[] args) throws Exception {
int delay = 1000;
String username = Base64.getEncoder().encodeToString(user.getBytes(StandardCharsets.UTF_8));
String password = Base64.getEncoder().encodeToString(pass.getBytes(StandardCharsets.UTF_8));
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket("smtp.gmail.com", 465);
br = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
dataOutputStream = new DataOutputStream(sslSocket.getOutputStream());
send("EHLO smtp.gmail.com\r\n",9);
send("AUTH LOGIN\r\n",1);
send(username+"\r\n",1);
send(password+"\r\n",1);
send("MAIL FROM:<xxxxxxxx#gmail.com>\r\n",1);
send("RCPT TO:<xxxxx#gmail.com>\r\n",1);
send("DATA\r\n",1);
send("Subject: Email test\r\n",0);
send("Email Body\r\n",0);
send(".\r\n",0);
send("QUIT\r\n",1);
}
private static void send(String s, int no_of_response_line) throws Exception
{
dataOutputStream.writeBytes(s);
System.out.println("CLIENT: "+s);
Thread.sleep(1000);
// Just reading the number of lines the server will respond.
for (int i = 0; i < no_of_response_line; i++) {
System.out.println("SERVER : " +br.readLine());
}
}
}
I am trying to ssh an appliance through java code and I encountered with errors. I am using
(http://www.jcraft.com/ )'s jar. Now here are my problems
How can I execuate multiple commands in chell using java? (jcreft lib or someother)
How can get output from following code (conversion of outputstream)
OutputStream out = System.out;
PrintStream ps = new PrintStream(out);
Here is code's snap
public static String LoginAppliance(String host, String ID )throws JSchException, InterruptedException, IOException
{
String result="";
String command = "_shell\n";
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, 22);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(10*1000);
Channel channel = session.openChannel("shell");
InputStream is = new ByteArrayInputStream(command.getBytes());
channel.setInputStream(is);
channel.setOutputStream(System.out);
OutputStream out = System.out;
PrintStream ps = new PrintStream(out);
channel.connect(15 * 1000);
Thread.sleep(3*1000);
channel.disconnect();
session.disconnect();
return (result);
}
It will really helpful for me.
Multiple commands can be separated by a semicolon (;) like:
String command = "echo 'hello';echo 'hello2'\n";
To get the result as a string instead of printing it to the console like:
ByteArrayOutputStream out = new ByteArrayOutputStream();
channel.setOutputStream(out);
...
return out.toString();
I misunderstood the question. I took a look on the documentation of Jsch and this was the easiest way for me to make it work:
import java.io.IOException;
import java.io.InputStream;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
public class Main {
public static void main(String[] args) {
String host = "theAddress";
String user = "root";
String password = "thePassword";
JSch jsch = new JSch();
Session session = null;
try {
session = jsch.getSession(user, host, 22);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(10000);
System.out.println("-->" + runCommand("echo 'hello'", session)); // -->hello
System.out.println("-->" + runCommand("whoami", session)); // -->root
System.out.println("-->" + runCommand("date", session)); // -->Thu Mar 13 23:45:39 CET 2014
} catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null) {
session.disconnect();
}
}
}
private static String runCommand(String string, Session session) {
ChannelExec channel = null;
try {
channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(string);
channel.connect();
return readOutput(channel);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (channel != null) {
channel.disconnect();
}
}
return null;
}
private static String readOutput(ChannelExec channel) throws IOException {
// code from: http://www.jcraft.com/jsch/examples/Exec.java.html
StringBuilder sb = new StringBuilder();
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;
sb.append(new String(tmp, 0, i));
}
if (channel.isClosed()) {
break;
}
try {
Thread.sleep(1000);
} catch (Exception e) {}
}
return sb.toString();
}
}