I'm trying to get my program to launch Enchanter to SSH into my server, but can't seem to figure out how to get in and output to go to stdin and stdout, or anywhere for that matter. I just get a blank output window in Netbeans. How to I get the Jar to run, and get input/output?
public class openShell {
public void openShell() throws IOException {
String line;
Scanner scan = new Scanner(System.in);
ProcessBuilder builder = new ProcessBuilder ("C:\\Program Files\\Java\\lib\\enchanter-beanshell-0.6.jar", "myscript.bsh");
builder.redirectErrorStream(true);
Process process = builder.start();
OutputStream stdin = process.getOutputStream ();
InputStream stderr = process.getErrorStream ();
InputStream stdout = process.getInputStream ();
BufferedReader reader = new BufferedReader (new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
while (scan.hasNext()) {
String input = scan.nextLine();
if (input.trim().equals("exit")) {
// Putting 'exit' amongst the echo --EOF--s below doesn't work.
writer.write("exit\n");
} else {
writer.write("((" + input + ") && echo --EOF--) || echo --EOF--\n");
}
writer.flush();
line = reader.readLine();
while (line != null && ! line.trim().equals("--EOF--")) {
System.out.println ("Stdout: " + line);
line = reader.readLine();
}
if (line == null) {
break;
}
}
}
}
private void LaunchButtonActionPerformed(ActionEvent evt) {
//openShell open = new openShell(); //RUNS BUT NO IN OR OUTPUT
//BELOW CODE IS FOR TESTING, JUST TRYING TO GET PROCESSBUILDER TO CONNECT
// TO MY JAR
try {
ProcessBuilder builder = new ProcessBuilder(
"Java -jar C:\\Program Files\\Java\\lib\\enchanter-beanshell-0.6.jar");
builder.redirectErrorStream(true);
Process process = builder.start();
} catch (IOException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
The method ProcessBuilder.inheritIO will redirect your command streams in your stdin, stdout and stderr. This applies to Java 7.
String[] args = {
"java",
"-jar",
"C:\\Program Files\\Java\\lib\\enchanter-beanshell-0.6.jar"
};
ProcessBuilder builder = new ProcessBuilder(args);
Start with breaking up the arguments as above. Then implement all the recommendations of When Runtime.exec() won't.
The methods Process.getInputStream and Process.getOutputStream will get you streams that you can then read from and write to.
Related
I have two processes defined by processBuilders:
ProcessBuilder pb1 = new ProcessBuilder (...)
ProcessBuilder pb2 = new ProcessBuilder (...)
I want the output of pb1 to be the input to pb2.
I found in the documentation that I can make the input of pb2 to be read from another process by using pipe:
pb2.redirectInput(Redirect.PIPE);
However, how can I specify that I want this pipe to read from the output of pb1?
static ProcessBuilder.Redirect INHERIT Indicates that subprocess I/O
source or destination will be the same as those of the current
process.
static ProcessBuilder.Redirect PIPE Indicates that subprocess I/O
will be connected to the current Java process over a pipe.
So I don't think one of these will help you redirecting the output of one process to
the input of another process. You have to implement it yourself.
Implementation:
public class RedirectStreams {
public RedirectStreams(Process process1, Process process2) {
final Process tmpProcess1 = process1;
final Process tmpProcess2 = process2;
new Thread(new Runnable() {
#Override
public void run() {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(tmpProcess1.getInputStream()));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(tmpProcess2.getOutputStream()));
String lineToPipe;
try {
while ((lineToPipe = bufferedReader.readLine()) != null){
System.out.println("Output process1 / Input process2:" + lineToPipe);
bufferedWriter.write(lineToPipe + '\n');
bufferedWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
This one can surely be designed nicer
and I haven't tested, if it runs's safe, but it does the job.
Usage:
RedirectStreams redirectStreams = new RedirectStreams(process1,process2);
Test:
public class ProcessPipeTest {
#Test public void testPipe(){
try {
Process process1 = new ProcessBuilder("/bin/bash").start();
Process process2 = new ProcessBuilder("/bin/bash").start();
RedirectStreams redirectStreams = new RedirectStreams(process1,process2);
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(process1.getOutputStream()));
String command = "echo echo echo";
System.out.println("Input process1: " + command);
bufferedWriter.write(command + '\n');
bufferedWriter.close();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process2.getInputStream()));
String actualOutput = bufferedReader.readLine();
System.out.println("Output process2: " + actualOutput);
assertEquals("echo",actualOutput);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Output:
Input process1: echo echo echo
Output process1 / Input process2:echo echo
Output process2: echo
As of JDK 9, you can use startPipeline like so:
ProcessBuilder.startPipeline(
Arrays.asList(
new ProcessBuilder(...),
new ProcessBuilder(...),
...
)
)
The uploaded Screenshot conatains the start_client.bat file content, viewed in notepad++ editor.
Currently am invoking start_client.bat on local machine it works fine but when the same bat file is invoked on server it pops up a window on server and it needs manual closure after execution. Any way to force bat file execution on server without window poppping up.
private void invokeSeagull(String flag) throws Exception
{
String path="";
if(flag.equals("Start"))
{
path="cmd /c start D:/Seagull/TIB/start_client.bat";
}
if(flag.equals("Stop"))
{
path="cmd /c start D:/Seagull/TIB/stop_client.bat";
}
try {
String line;
Process p = Runtime.getRuntime().exec(path);
p.waitFor();
BufferedReader bri = new BufferedReader
(new InputStreamReader(p.getInputStream()));
BufferedReader bre = new BufferedReader
(new InputStreamReader(p.getErrorStream()));
while ((line = bri.readLine()) != null) {
System.out.println(line);
}
bri.close();
while ((line = bre.readLine()) != null) {
System.out.println(line);
}
bre.close();
p.waitFor();
System.out.println("Done.");
}
catch (Exception err) {
err.printStackTrace();
}
}
This code snippet should run batch file, of course if you use Windows.
Runtime.getRuntime().exec("cmd /c start {pathToFile}");
As pointed out be ssedano the correct way to execute shell commands in Java is the Process-builder:
// Just the name of an executable is enough
final ProcessBuilder pb = new ProcessBuilder( "test.bat" );
pb.redirectError( Redirect.INHERIT );
pb.redirectOutput( Redirect.INHERIT );
System.out.println( String.format( "***** Running Process %s OUTPUT:", pb.command().toString() ) );
final Process process = pb.start();
process.getOutputStream().close();
final int returnCode = process.waitFor();
System.out.println( "***** Process Exited with Returncode: " + returnCode );
You can just redirect STDERR and STDOUT of the bat-file, so you will get all output in the Server-Output console. And you should close STDIN of the bat-file, so it will exit and not get stuck on the pause command at the end!
You could use the new in Java 7 ProcessBuilder
A simple example:
String[] command = {"CMD", "/C", "dir"};
ProcessBuilder probuilder = new ProcessBuilder(command);
// Set up your work directory
probuilder.directory(new File("c:\\stackoverflow"));
Process process = probuilder.start();
// Read output
try (InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);)
{
String line;
System.out.printf("Output of running %s is:\n", Arrays.toString(command));
while ((line = br.readLine()) != null)
{
System.out.println(line);
}
// Wait to get exit value
int exitValue = process.waitFor();
}
catch (Exception e)
{
// Fail
}
This should run in the silent mode :
Runtime.getRuntime().exec(new String[] {"cmd", "/pathto/start_client.bat"});
I am trying to dump a MySQL database within my Java application the following way:
String[] command = new String[] {"cmd.exe", "/c", "C:/mysql/mysqldump.exe" --quick --lock-tables --user=\"root\" --password=\"mypwd\" mydatabase > \"C:/mydump.sql\""};
Process process = Runtime.getRuntime().exec(command);
int exitcode = process.waitFor();
The process fails with exit-code 6. I somewhere read that the operand ">" is not correctly interpreted and there was the hint to use "cmd.exe /c" as prefix. But it still doesn't work.
Any ideas?
Yes, you are right , some days ago I made class for exporting DataBase from MySQL...
You coud read output sream from console and then write to file
String[] command = new String[] {"cmd.exe", "/c", "\"C:/Program Files/MySQL/MySQL Server 5.6/bin/mysqldump.exe\" --quick --lock-tables --user=\"root\" --password=\"mypwd\" mydatabase "};
Process process = Runtime.getRuntime().exec(command);
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line); //there you can write file
}
input.close();
Best Regards
Okay here's the final solution. You need to put the "process-reader to file-writer" code into a separate thread and finally wait for the process object to be finished:
// define backup file
File fbackup = new File("C:/backup.sql");
// execute mysqldump command
String[] command = new String[] {"cmd.exe", "/c", "C:/path/to/mysqldump.exe --quick --lock-tables --user=myuser --password=mypwd mydatabase"};
final Process process = Runtime.getRuntime().exec(command);
// write process output line by line to file
if(process!=null) {
new Thread(new Runnable() {
#Override
public void run() {
try{
try(BufferedReader reader = new BufferedReader(new InputStreamReader(new DataInputStream(process.getInputStream())));
BufferedWriter writer = new BufferedWriter(new FileWriter(fbackup))) {
String line;
while((line=reader.readLine())!=null) {
writer.write(line);
writer.newLine();
}
}
} catch(Exception ex){
// handle or log exception ...
}
}
}).start();
}
if(process!=null && process.waitFor()==0) {
// success ...
} else {
// failed
}
On Linux you can directly re-direct the output of the command to a file by using ">" as usual... (and also on Mac OS X I think). So no need for the thread. Generally, please avoid white spaces in your path to the mysqldump/mysqldump.exe file!
This question already has answers here:
Executing a Java application in a separate process
(9 answers)
Closed 7 years ago.
Is there a way to run this command line within a Java application?
java -jar map.jar time.rel test.txt debug
I can run it with command but I couldn't do it within Java.
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("java -jar map.jar time.rel test.txt debug");
http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html
You can also watch the output like this:
final Process p = Runtime.getRuntime().exec("java -jar map.jar time.rel test.txt debug");
new Thread(new Runnable() {
public void run() {
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
try {
while ((line = input.readLine()) != null)
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
p.waitFor();
And don't forget, if you are running a windows command, you need to put cmd /c in front of your command.
EDIT: And for bonus points, you can also use ProcessBuilder to pass input to a program:
String[] command = new String[] {
"choice",
"/C",
"YN",
"/M",
"\"Press Y if you're cool\""
};
String inputLine = "Y";
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
writer.write(inputLine);
writer.newLine();
writer.close();
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
This will run the windows command choice /C YN /M "Press Y if you're cool" and respond with a Y. So, the output will be:
Press Y if you're cool [Y,N]?Y
To avoid the called process to be blocked if it outputs a lot of data on the standard output and/or error, you have to use the solution provided by Craigo. Note also that ProcessBuilder is better than Runtime.getRuntime().exec(). This is for a couple of reasons: it tokenizes better the arguments, and it also takes care of the error standard output (check also here).
ProcessBuilder builder = new ProcessBuilder("cmd", "arg1", ...);
builder.redirectErrorStream(true);
final Process process = builder.start();
// Watch the process
watch(process);
I use a new function "watch" to gather this data in a new thread. This thread will finish in the calling process when the called process ends.
private static void watch(final Process process) {
new Thread() {
public void run() {
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
try {
while ((line = input.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
Runtime.getRuntime().exec("java -jar map.jar time.rel test.txt debug");
import java.io.*;
Process p = Runtime.getRuntime().exec("java -jar map.jar time.rel test.txt debug");
Consider the following if you run into any further problems, but I'm guessing that the above will work for you:
Problems with Runtime.exec()
what about
public class CmdExec {
public static Scanner s = null;
public static void main(String[] args) throws InterruptedException, IOException {
s = new Scanner(System.in);
System.out.print("$ ");
String cmd = s.nextLine();
final Process p = Runtime.getRuntime().exec(cmd);
new Thread(new Runnable() {
public void run() {
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
try {
while ((line = input.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
p.waitFor();
}
}
Have you tried the exec command within the Runtime class?
Runtime.getRuntime().exec("java -jar map.jar time.rel test.txt debug")
Runtime - Java Documentation
Process p = Runtime.getRuntime().exec("java -jar map.jar time.rel test.txt debug");
Im using java to start a GNOME terminal process in linux and redirecting its input and output to my code. Below is a code.
public static void main(String[] args) throws InterruptedException
{
// TODO Auto-generated method stub /usr/bin/telnet
try
{
String line, commandInput;
Scanner scan = new Scanner(new File("/home/Ashutosh/Documents/testfile"));
ProcessBuilder telnetProcessBuilder = new ProcessBuilder("/bin/bash");///home/Ashutosh/Documents/tempScript");
telnetProcessBuilder.redirectErrorStream(true);
Process telnetProcess = telnetProcessBuilder.start();
//Process telnetProcess = Runtime.getRuntime().exec("xterm");///home/Ashutosh/Documents/tempScript");
BufferedReader input = new BufferedReader(new InputStreamReader(telnetProcess.getInputStream()));
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(telnetProcess.getOutputStream()));
while(scan.hasNext())
{
commandInput = scan.nextLine();
output.write(commandInput);
/* if(commandInput.trim().equals("exit"))
{
output.write("exit\r");
}
else
{
output.write("((" + commandInput + ") && echo --EOF--) || echo --EOF--\r");
}
*/ output.flush();
line = input.readLine();
while(line != null && !line.trim().equals("--EOF--"))
{
System.out.println(line);
line = input.readLine();
}
if(line == null)
break;
}
/* Thread.sleep(500);
output.write("/home/Ashutosh/Documents/testfile\r");
Thread.sleep(500);
output.flush();
while((line = input.readLine())!= null)
System.out.println(line);
telnetProcess.destroy();
*/ //String s = input.readLine();
//System.out.print(s + "\r\n");
//s = input.readLine();
//System.out.print(s + "\r\n");
}
the contents of testfile which is bash script is
#!/bin/bash
ls -l
pwd
date
exit
and i also tried the following interactive script which takes input from user which i want to redirect from java code is given
#! /bin/bash
echo "Input any number form 0-3:"
read num
case $num in
0) echo "You are useless";;
1) echo "You are number 1";;
2) echo "Too suspecious";;
3) echo "Thats all man, got to go...!";;
*) echo "Cant't u read english, this is wrong choice";;
esac
read
exit
my code stops at input.readLine(); im not sure but i think i am not able to redirect the output stream
output.write(commandInput);
command is executing well but did not write i intended to on the process redirected input, that is why it hangs at readLine();.
If somebody have already solved please let me know the solution.
From following link i tried to solve the issue but still no luck:
Java Process with Input/Output Stream
Thanks
Ashutosh
readLine() read the contents of a line, without the newline at the end.
write() writes just the text, it doesn't add a new line.
Perhaps you want to add write("\n"); or use PrintStream or PrintWriter.
I imagine, your script is being sent as
#!/bin/bashls -lpwddateexit
which is a comment without a newline.
EDIT: Huge error, not adding the command to the ProcessBuilder!!
Why are you not just running your script as a Linux script? That is,
ProcessBuilder builder = new ProcessBuilder();
LinkedList<String> command = new LinkedList<String>();
command.add("/bin/bash");
command.add("/home/Ashutosh/Documents/testfile");
builder.command(command);
Process myProc = builder.start();
Also, I notice the variable is named 'telnetProcess' yet there is no invocation of telnet anywhere that I can see. Perhaps this is the problem?
EDIT: Added my suggestion below for the interactive script.
ProcessBuilder builder = new ProcessBuilder();
LinkedList<String> command = new LinkedList<String>();
command.add("/bin/bash");
command.add("/path/to/interactiveScript");
builder.command(command);
final Process myProc = builder.start();
// Java input goes to process input.
Thread inputParser = new Thread() {
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(myProc.getOutputStream()));
String line = "";
while(line != null) {
line = br.readLine();
bw.write(line);
bw.newLine();
}
}
}.start();
// Process output must go to Java output so user can see it!
Thread outputParser = new Thread() {
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(myProc.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = "";
while(line != null) {
line = br.readLine();
bw.write(line);
bw.newLine();
}
}
}.start();
hi guys sorry for late response, after some trials i got it working. I am simply letting the process completing its process and exit normally rather than forcefully and then the BufferedReader and BufferedWriter keeps the string buffers in RAM which i can read now after process exit with code 0.
public static void main(String[] args) throws InterruptedException
{
// TODO Auto-generated method stub
try
{
String line, commandInput;
ProcessBuilder telnetProcessBuilder = new ProcessBuilder("/bin/bash");
telnetProcessBuilder.redirectErrorStream(true);
Process telnetProcess = telnetProcessBuilder.start();
BufferedReader input = new BufferedReader(new InputStreamReader(telnetProcess.getInputStream()));
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(telnetProcess.getOutputStream()));
commandInput = "ls -l\n";
output.write(commandInput);
output.flush();
commandInput = "pwd\n";
output.write(commandInput);
output.flush();
commandInput = "whoami\n";
output.write(commandInput);
output.flush();
commandInput = "exit\n";
output.write(commandInput);
output.flush();
while((line = input.readLine())!= null)
System.out.println(line);
}
}