My requirement is to connect to some server through telnet using a java program and run few commands and read the responses. Based on these responses I need to perform some operation
I strated with https://stackoverflow.com/a/1213188/1025328
I'm using commons-net and my program is something like this:
public class TelnetSample {
private TelnetClient telnet;
private InputStream in;
private PrintStream out;
public TelnetSample(String server, int port) {
try {
// Connect to the specified server
telnet = new TelnetClient();
telnet.connect(server, port);
in = telnet.getInputStream();
out = new PrintStream(telnet.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
public String readResponse() {
System.out.println("TelnetSample.readResponse()");
StringBuilder out = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(out.toString());
System.out.println("==========================================================");
return out.toString();
}
public String read2() {
System.out.println("TelnetSample.read()");
StringBuffer sb = new StringBuffer();
try {
int available = in.available();
for (int index = 0; index < available; index++) {
char ch = (char) in.read();
System.out.print(ch);
sb.append(ch);
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
public String sendCommand(String command) {
try {
InputStream is = new ByteArrayInputStream(command.getBytes());
int ch;
while ((ch = is.read()) != -1) {
out.write(ch);
out.flush();
}
System.out.println(command);
String output = read2();
if (output.trim().isEmpty()) {
System.out.println("output empty");
} else {
System.out.println(output);
}
System.out.println("==========================================================");
return output;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void disconnect() {
try {
telnet.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
TelnetSample telnet = new TelnetSample("aspmx2.xxxxxx.com", 25);
telnet.readResponse();
telnet.sendCommand("Helo hi");
telnet.sendCommand("mail from:xyz#testmail.com");
telnet.sendCommand("rcpt to:pk#testmail.com");
telnet.sendCommand("quit");
telnet.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here apart form the telnet connection response, for every other sendCommand I'm getting an empty response. Can some one point me what could be the issue.
My output is something like this
TelnetSample.readResponse()
220 mx.xxxxxx.com ESMTP o86si4086625pfi.217 - gsmtp
==========================================================
Helo hi
TelnetSample.read()
output empty
==========================================================
mail from:xyz#testmail.com
TelnetSample.read()
output empty
==========================================================
rcpt to:pk#testmail.com
TelnetSample.read()
output empty
==========================================================
quit
TelnetSample.read()
output empty
==========================================================
This code has several issue:
the first issue is in readResponse method. When you use
readLine() you can easy block your code and will wait forever. Please have a look at discussion How to determine the exact state of a BufferedReader?
the second you don't send any CR/LF chars. Server got your requests like a single line. Ex:
mail from:xyz#testmail.comrcpt to:pk#testmail.comquit
To fix first issue you can choose several ways:
use multi-threading model
use NIO API. I would recommend Netty for that. Especially for your case as i can see you didn't use Telnet protocol at all, you connected to SMTP server.
Quick fix but the worst, wait first line from server and go on:
public String readResponse() {
System.out.println("TelnetSmtpSample.readResponse()");
StringBuilder out = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
out.append(reader.readLine());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(out.toString());
System.out.println("=====================");
return out.toString();
}
To fix second one:
telnet.sendCommand("Helo hi\r\n");
telnet.sendCommand("mail from:xyz#testmail.com\r\n");
telnet.sendCommand("rcpt to:pk#testmail.com\r\n");
telnet.sendCommand("quit\r\n");
It's possible read2 is getting a null value back from the input stream before data is actually returned. Try something like this:
private String read2() {
StringBuffer sb = new StringBuffer();
try {
do {
if (in.available() > 0) {
char ch = (char) in.read();
sb.append(ch);
} else {
Thread.sleep(1000);
}
} while (in.available()>0);
String output = new String(sb);
return output;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
We wanted to execute some commands on Windows Server 2008/Windows 7 using telnet. As everytime logining in and running commands on around 50 of the same is tedious so I searched in google and zeored to apache commons and I found an example.
It works but it is printing some junk characters (I'm thinking it is some issue with character encoding of Windows, I'm new to this).
package com.kiran.telnet;
import org.apache.commons.net.telnet.TelnetClient;
import java.io.InputStream;
import java.io.PrintStream;
public class AutomatedTelnetClient {
private TelnetClient telnet = new TelnetClient();
private InputStream in;
private PrintStream out;
private String prompt = ">";
public AutomatedTelnetClient(String server, String user, String password) {
try {
// Connect to the specified server
telnet.connect(server, 23);
// Get input and output stream references
in = telnet.getInputStream();
out = new PrintStream(telnet.getOutputStream(), true);
// Log the user on
readUntil("login: ");
write(user);
readUntil("password: ");
write(password);
// Advance to a prompt
readUntil(prompt + " ");
} catch (Exception e) {
e.printStackTrace();
}
}
public void su(String password) {
try {
write("su");
readUntil("Password: ");
write(password);
prompt = ">";
readUntil(prompt + " ");
} catch (Exception e) {
e.printStackTrace();
}
}
public String readUntil(String pattern) {
try {
char lastChar = pattern.charAt(pattern.length() - 1);
StringBuffer sb = new StringBuffer();
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 (Exception e) {
e.printStackTrace();
}
return null;
}
public void write(String value) {
try {
out.println(value);
out.flush();
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
}
}
public String sendCommand(String command) {
try {
write(command);
return readUntil(prompt);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void disconnect() {
try {
telnet.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
AutomatedTelnetClient telnet = new AutomatedTelnetClient(
"127.0.0.1", "Kiran", "artha");
System.out.println("Got Connection...");
telnet.sendCommand("hostname");
//telnet.sendCommand("ipconfig");
//telnet.sendCommand("ps -ef ");
//System.out.println("run command");
//telnet.sendCommand("ls ");
//System.out.println("run command 2");
telnet.disconnect();
System.out.println("DONE");
} catch (Exception e) {
e.printStackTrace();
}
}
}
The Output while I run this is:
Welcome to Microsoft Telnet Service
login: Kiran
Kiran
password: artha
[1;1H*=============================================================== [2;1HMicrosoft Telnet Server. [3;1H*=============================================================== [4;1HC:\Users\Kiran> Got Connection...
hostname
[5;1H[K[6;1H[K[7;1H[K[8;1H[K[9;1H[K[10;1H[K[11;1H[K[12;1H[K[13;1H[K[14;1H[K[15;1H[K[16;1H[K[17;1H[K[18;1H[K[19;1H[K[20;1H[K[21;1H[K[22;1H[K[23;1H[K[24;1H[K[25;1H[K[4;16Hhostname[5;1HKiran-PC[7;1HC:\Users\Kiran>DONE
And some ESC char before "["
Any help regarding this one.
Thank You.
Take a look at this wiki article. This symbols are just control characters, used to format the output in your terminal.
You can try to configure your terminal type like:
TelnetClient telnet = new TelnetClient("dumb");
Or you can try to configure it with TerminalTypeOptionHandler.
By default your telnet client is created with terminal type vt100' which supports control sequences. The dumb one does not support them. But you have to understand, that it is not guaranteed, that remote server support this terminal type.
Hi I'm about to write a programm which starts multiple minecraft servers:
If you type 'start servername', it starts this server.
If you type 'watch servername', the program shows the output of this server and you should be able to send commands (to this server) at the same time until you type sth. like 'exit'. The problem is that I don't know how to refresh the outputscreen and take the inputs from the keyboard at the same time.
Here is my code from the server class:
class Server{
private String name;
private StartCommand command;
private boolean on = false;
private Process p = null;
public Server(StartCommand c, String name){
this.command = c;
this.name = name;
}
public void start(){
try {
p = Runtime.getRuntime().exec(command.getCommand());
System.out.println("Server: " + name + " is on now!");
on = true;
} catch (IOException e) {
e.printStackTrace();
on = false;
}
}
public void watch(){
try{
Scanner sc = new Scanner(System.in);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
on = false;
}
}
}
I hope you can help me.
Greetings,
Fabian
Server console should be displayed in separate terminal and client console where user can type in the command.
Similar to any server like mysql has a log where server output's are displayed. mysql client command where user type in their sql commands.
Or else redirect watch output to a file and then type the next command.
I am trying to execute a c++ code from java on a remote Windows machine. In order to deal with the remote part, I have created a Web service from where the actual command is run using Runtime.exec(). The c++ exe is not being called directly from the java code. I have a batch file that eventually calls the exe.
The problem is, both java and c++ processes hang. The java code on server side does handle the output stream and error stream. Also, the c++ code is logging everything in a file on Windows. The strange thing is that, when I remove the WS call and run the java code on server side as a standalone java program, it succeeds. Here is the java code:
public class RunCPlusPlusExecutable {
public int runExecutable() {
int exitValue = 0;
try {
Process p = null;
Runtime rt = Runtime.getRuntime();
System.out.println("About to execute" + this + rt);
p = rt.exec("c:/temp/execcplusplus.bat");
System.out.println("Process HashCode=" + p.hashCode());
StreamProcessor errorHandler = new StreamProcessor(p.getErrorStream(), "Error");
StreamProcessor outputHandler = new StreamProcessor(p.getInputStream(), "Output");
errorHandler.start();
outputHandler.start();
exitValue = p.waitFor();
System.out.println("Exit value : " + exitValue);
if (exitValue == 0)
System.out.println("SUCCESS");
else
System.out.println("FAILURE");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
}
return exitValue;
}
class StreamProcessor extends Thread {
private InputStream is = null;
private String type = null;
private InputStreamReader isr = null;
private BufferedReader br = null;
private FileWriter writer = null;
private BufferedWriter out = null;
StreamProcessor(InputStream is, String type) {
this.is = is;
this.type = type;
}
public void run() {
try {
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
writer = new FileWriter("*******path to log file********");
out = new BufferedWriter(writer);
String line = null;
while ((line = br.readLine()) != null) {
Date date = new Date();
out.write("[" + type + "]: " + date + " : " + line);
out.newLine();
}
writer.flush();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
try {
if (br != null)
br.close();
if (isr != null)
isr.close();
if (out != null)
out.close();
if (writer != null)
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Any idea what is causing the problem and how to debug it? Please note that I won't be able to debug the c++ code.
Thanks
Update 1:
Here are some more details...
The WS server is running from some admin user. And I have been running the standalone java program from some other user.
*It seems that the c++ executable is giving referenced memory error while executing from WS call. There are pop-ups citing the error with OK and Cancel buttons. *
Update 2:
The tomcat server where the WS is deployed is running as a Windows NT service. Can that be the cause of the error? If yes, how to resolve this?
I want to create diff of two files. I tried searching for code in Java that does it, but didnt find any simple code/ utility code for this. Hence, I thought if I can somehow run linux diff/sdiff command from my java code and make it return a file that stores the diff then it would be great.
Suppose there are two files fileA and fileB. I should be able to store their diff in a file called fileDiff through my java code. Then fetching data from fileDiff would be no big deal.
You can use java.lang.Runtime.exec to run simple code. This gives you back a Process and you can read its standard output directly without having to temporarily store the output on disk.
For example, here's a complete program that will showcase how to do it:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class testprog {
public static void main(String args[]) {
String s;
Process p;
try {
p = Runtime.getRuntime().exec("ls -aF");
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((s = br.readLine()) != null)
System.out.println("line: " + s);
p.waitFor();
System.out.println ("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {}
}
}
When compiled and run, it outputs:
line: ./
line: ../
line: .classpath*
line: .project*
line: bin/
line: src/
exit: 0
as expected.
You can also get the error stream for the process standard error, and output stream for the process standard input, confusingly enough. In this context, the input and output are reversed since it's input from the process to this one (i.e., the standard output of the process).
If you want to merge the process standard output and error from Java (as opposed to using 2>&1 in the actual command), you should look into ProcessBuilder.
You can also write a shell script file and invoke that file from the java code. as shown below
{
Process proc = Runtime.getRuntime().exec("./your_script.sh");
proc.waitFor();
}
Write the linux commands in the script file, once the execution is over you can read the diff file in Java.
The advantage with this approach is you can change the commands with out changing java code.
You need not store the diff in a 3rd file and then read from in. Instead you make use of the Runtime.exec
Process p = Runtime.getRuntime().exec("diff fileA fileB");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
try to use unix4j. it s about a library in java to run linux command. for instance if you got a command like:
cat test.txt | grep "Tuesday" | sed "s/kilogram/kg/g" | sort
in this program will become:
Unix4j.cat("test.txt").grep("Tuesday").sed("s/kilogram/kg/g").sort();
You can call run-time commands from java for both Windows and Linux.
import java.io.*;
public class Test{
public static void main(String[] args)
{
try
{
Process process = Runtime.getRuntime().exec("pwd"); // for Linux
//Process process = Runtime.getRuntime().exec("cmd /c dir"); //for Windows
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line=reader.readLine())!=null)
{
System.out.println(line);
}
}
catch(Exception e)
{
System.out.println(e);
}
finally
{
process.destroy();
}
}
}
Hope it Helps.. :)
Runtime run = Runtime.getRuntime();
//The best possible I found is to construct a command which you want to execute
//as a string and use that in exec. If the batch file takes command line arguments
//the command can be constructed a array of strings and pass the array as input to
//the exec method. The command can also be passed externally as input to the method.
Process p = null;
String cmd = "ls";
try {
p = run.exec(cmd);
p.getErrorStream();
p.waitFor();
}
catch (IOException e) {
e.printStackTrace();
System.out.println("ERROR.RUNNING.CMD");
}finally{
p.destroy();
}
The suggested solutions could be optimized using commons.io, handling the error stream, and using Exceptions. I would suggest to wrap like this for use in Java 8 or later:
public static List<String> execute(final String command) throws ExecutionFailedException, InterruptedException, IOException {
try {
return execute(command, 0, null, false);
} catch (ExecutionTimeoutException e) { return null; } /* Impossible case! */
}
public static List<String> execute(final String command, final long timeout, final TimeUnit timeUnit) throws ExecutionFailedException, ExecutionTimeoutException, InterruptedException, IOException {
return execute(command, 0, null, true);
}
public static List<String> execute(final String command, final long timeout, final TimeUnit timeUnit, boolean destroyOnTimeout) throws ExecutionFailedException, ExecutionTimeoutException, InterruptedException, IOException {
Process process = new ProcessBuilder().command("bash", "-c", command).start();
if(timeUnit != null) {
if(process.waitFor(timeout, timeUnit)) {
if(process.exitValue() == 0) {
return IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8);
} else {
throw new ExecutionFailedException("Execution failed: " + command, process.exitValue(), IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8));
}
} else {
if(destroyOnTimeout) process.destroy();
throw new ExecutionTimeoutException("Execution timed out: " + command);
}
} else {
if(process.waitFor() == 0) {
return IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8);
} else {
throw new ExecutionFailedException("Execution failed: " + command, process.exitValue(), IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8));
}
}
}
public static class ExecutionFailedException extends Exception {
private static final long serialVersionUID = 1951044996696304510L;
private final int exitCode;
private final List<String> errorOutput;
public ExecutionFailedException(final String message, final int exitCode, final List<String> errorOutput) {
super(message);
this.exitCode = exitCode;
this.errorOutput = errorOutput;
}
public int getExitCode() {
return this.exitCode;
}
public List<String> getErrorOutput() {
return this.errorOutput;
}
}
public static class ExecutionTimeoutException extends Exception {
private static final long serialVersionUID = 4428595769718054862L;
public ExecutionTimeoutException(final String message) {
super(message);
}
}
if the opening in windows
try {
//chm file address
String chmFile = System.getProperty("user.dir") + "/chm/sample.chm";
Desktop.getDesktop().open(new File(chmFile));
} catch (IOException ex) {
Logger.getLogger(Frame.class.getName()).log(Level.SEVERE, null, ex);
{
JOptionPane.showMessageDialog(null, "Terjadi Kesalahan", "Error", JOptionPane.WARNING_MESSAGE);
}
}
ProcessBuilder processBuilder = new ProcessBuilder();
// -- Linux --
// Run a shell command
processBuilder.command("bash", "-c", "ls /home/kk/");
// Run a shell script
//processBuilder.command("path/to/hello.sh");
// -- Windows --
// Run a command
//processBuilder.command("cmd.exe", "/c", "dir C:\\Users\\kk");
// Run a bat file
//processBuilder.command("C:\\Users\\kk\\hello.bat");
try {
Process process = processBuilder.start();
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println(output);
System.exit(0);
} else {
//abnormal...
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}