running multiple cmd commands through java separated by some another code - java

I want to start a cmd command, then after the first command is done, I want to run a code to adjust some text in a file, then execute another command on the same cmd window. I don't know how to do that and everywhere I looked the answer is for the commands after each other which is not this case. the code for editing the text works fine without starting the cmd but if I execute the cmd command it does not change. code below.
public static void main(String[] args)throws IOException
{
try
{
Main m1 = new Main();
Process p= Runtime.getRuntime().exec("cmd /c start C:/TERRIERS/terrier/bin/trec_setup.bat");
p.waitFor();
/*code to change the text*/
m1.answerFile(1);
m1.questionFile(1);
/**********************/
//code to add another command here (SAME WINDOW!)
/************************/
}
catch(IOException ex){
}
catch(InterruptedException ex){
}

Execute cmd and send your command lines (.bat) to the standard input.
Process p = Runtime.getRuntime().exec("cmd");
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null)
System.out.println(line);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
try (PrintStream out = new PrintStream(p.getOutputStream())) {
out.println("C:/TERRIERS/terrier/bin/trec_setup.bat");
out.println("another.bat");
// .....
}
p.waitFor();

For starters, the \C option terminates CMD after executing the initial command. Use \K instead.
You won't be able to use waitFor() to detect when the initial command is done, because if you wait until the CMD terminates, you won't be able to re-use the same process.
Instead, you'll need to read the output of CMD process to detect when the batch file is complete and you are prompted for another command. Then write the next command line that you want to execute though the input stream of the Process.
Sounds like a pain. Why would do you need to use the same window?

Related

Open a new command prompt and send commands from a Java program running in a command prompt

I have a Java program running in a command prompt (A) and would like to open a new command prompt (B), run some commands in B, and then close the B command prompt window.
I have been using these posts as reference:
Create a new cmd.exe window from within another cmd.exe prompt
How to open a command prompt and input different commands from a java program
I was able to open a command prompt from my Java program, How to run some exe in this command prompt using java code?
pass multiple parameters to ProcessBuilder with a space
Start CMD by using ProcessBuilder
Here is my code:
public static void startCMD(String appName) {
// init shell
String[] cmd = new String[]{"cmd.exe", "/C", "start"};
ProcessBuilder builder = new ProcessBuilder(cmd);
Process p = null;
try {
p = builder.start();
} catch (IOException e) {
System.out.println(e);
}
// get stdin of shell
BufferedWriter p_stdin = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
// execute the desired command (here: ls) n times
try {
// single execution
p_stdin.write("C:");
p_stdin.newLine();
p_stdin.flush();
p_stdin.write("cd C:\\" + appName);
p_stdin.newLine();
p_stdin.flush();
p_stdin.write("sbt \"run 8080\"");
p_stdin.newLine();
p_stdin.flush();
} catch (IOException e) {
System.out.println(e);
}
// finally close the shell by execution exit command
try {
p_stdin.write("exit");
p_stdin.newLine();
p_stdin.flush();
} catch (IOException e) {
System.out.println(e);
}
// write stdout of shell (=output of all commands)
Scanner s = new Scanner(p.getInputStream());
while (s.hasNext()) {
System.out.println(s.next());
}
s.close();
}
The code above opens a new command prompt (B), but none of the commands are entered in this new command prompt (B). The current Java program just hangs in the command prompt (A).
I know I am missing some commands and parameters to have the command prompt (B) to close when the process is finished.
Is there a better way to build this?
I appreciate the help.

BufferedReader pauses on .readLine() when using ProcessBuilder to execute simple Python script

I'm trying to use ProcessBuilder to execute a simple python script from CMD, which prints to the command line, then have that text read into Java and outputted through System.out.println() in netbeans. My issue is the BufferedReader seems to pause at .readLine() then output the text in bulk once the py script has stopped running, as opposed to outputting live.
My process is as follows:
[execute python script]
Executors.newSingleThreadExecutor().execute(this::TEST);
[run execution]
public void TEST(){
try {
ProcessBuilder py = new ProcessBuilder("cmd", "/C", "C:\\Users\\Documents\\TEST.py");
String readLine;
Process launch = py.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(launch.getInputStream()));
while((readLine = reader.readLine()) != null){
System.out.println(readLine);
}
} catch (IOException ex) {Logger.getLogger(Template.class.getName()).log(Level.SEVERE, null, ex);}
}
[here is the python script i wish to run and read live]
import Tkinter, tkFileDialog, tkMessageBox
root = Tkinter.Tk()
root.withdraw()
root.resizable(width=Tkinter.TRUE, height=Tkinter.TRUE)
root.geometry('{}x{}'.format(400,600))
print("hello1\n")
print("hello2\n")
print("hello3\n")
print("hello4\n")
print("hello5\n")
tkMessageBox.showinfo("Complete!", "testing")
print("hello6\n")
print("hello7\n")
print("hello8\n")
print("hello9\n")
print("hello10\n")
tkMessageBox.showinfo("Complete!", "testing")
Thanks!!!
First: Your command does not do anything. It is cmd /C C:\Users\Documents\TEST.py which does nothing but tell you that C:\Users\Documents\TEST.py is not a command. You would need to call cmd /C start C:\Users\Documents\TEST.py for it to do something.
Still this won't make your code work. The problem here is that you are invoking a cmd in there you start a python process. When you now grab the input stream you are getting the cmd input stream which is not the one you are looking for.
In order to get it to work invoke python directly by calling python C:\Users\Documents\TEST.py. Make sure python is in your PATH for this to work.
Your code should then look something like this:
try
{
ProcessBuilder py = new ProcessBuilder("python", "C:\\Users\\Documents\\TEST.py");
String readLine;
Process launch = py.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(launch.getInputStream()));
while ((readLine = reader.readLine()) != null)
{
System.out.println(readLine);
}
}
catch (IOException ex)
{
Logger.getLogger(Template.class.getName()).log(Level.SEVERE, null, ex);
}
This gives you exactly the result you were looking for.
A common problem can be that you did not flush your python std out. I recommend adding
import sys
# your code here...
sys.stdout.flush()
to your code to flush your python output.

Write to input stream of opened terminal

I am having trouble writing to a command prompt that I can open via ProcessBuilder.
I have the following:
public class Terminal {
public static void main(String[] args) {
List<String> launch = new ArrayList<String>();
launch.add("cmd");
launch.add("/c");
launch.add("start");
launch.add("cmd.exe");
launch.add("/k");
try {
ProcessBuilder builder = new ProcessBuilder(launch);
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(stdin));
w.write("dir");
w.flush();
w.close();
}
catch (IOException io) {
io.printStackTrace();
}
}
}
And this successfully opens a new Windows command prompt. But it never writes dir to it. The prompt just opens and only displays the directory from which java Terminal was issued.
How can I actively write to a terminal opened via a Process?
Edit:
If I change the command string list to "cmd.exe /k start dir" then the newly spawned command prompt does in fact issue the "dir" command and display it in the new terminal. I cannot seem to find the correct manner to access the stream for writing new commands to it.
public class Terminal {
public static void main(String[] args) {
List<String> launch = new ArrayList<String>();
launch.add("cmd");
launch.add("/k");
launch.add("start");
launch.add("dir");
try {
Process p = new ProcessBuilder(launch).start();
}
catch (IOException io) {
io.printStackTrace();
}
}
}
Lets take a look at what cmd /c start cmd /k does:
cmd /c starts a command prompt, executes the following commands, then exits.
start spawns a new process with the given commands
cmd /k expects a command (which you dont provide), executes it, then remains open
So: You start two instances of cmd. The second instance is started using start, which spawns a new process. You expect "dir" to show up in the second process, while it is being written to the first. Unfortunately, the first terminates immediately after calling start since you started it with /c.
Try changing /c to /k, then the "dir" should show up in the first window.

Execute commands in CMD on Windows with Java code

I want to write a Java code that would perform commands in Windows CMD.
I looked through the site and found out how to send and work with single request. For example create new Process and in execute ("cmd /c dir") then using input stream I can get the answer that is displayed.
How to open the process of cmd and let the user to enter cmd commands?
For example, I open application and it directly opens cmd process, then user can type "dir" and get the output.
After type "cd ../../"
and after type "dir" again and get the output with new path containment.
If it can be performed then how to do it? Or in order to perform this need to open each time a new process and execute ("cmd /c some_reqests")?
Nice question, you can in fact call cmd as a new process and use standard input and standard output to process data.
The tricky part is knowing when the stream from a command has ended.
To do so I used a string echoed right after the command (dir && echo _end_).
In practice I think it would be better to simply start a process for each task.
public class RunCMD {
public static void main(String[] args) {
try {
Process exec = Runtime.getRuntime().exec("cmd");
OutputStream outputStream = exec.getOutputStream();
InputStream inputStream = exec.getInputStream();
PrintStream printStream = new PrintStream(outputStream);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
printStream.println("chcp 65001");
printStream.flush();
printStream.println("dir && echo _end_");
printStream.flush();
for(String line=reader.readLine();line!=null;line=reader.readLine()){
System.out.println(line);
if(line.equals("_end_")){
break;
}
}
printStream.println("exit");
printStream.flush();
for(String line=reader.readLine();line!=null;line=reader.readLine()){
System.out.println(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
try this
Process p = Runtime.getRuntime().exec("ps -ef");
found it at http://alvinalexander.com/java/edu/pj/pj010016

how to launch a shell script in a new gnome terminal, from a java program

I'm trying to run a shell script (say myscript.sh) from a java program.
when i run the script from terminal, like this :
./myscript.sh
it works fine.
But when i call it from the java program, with the following code :
try
{
ProcessBuilder pb = new ProcessBuilder("/bin/bash","./myScript.sh",someParam);
pb.environment().put("PATH", "OtherPath");
Process p = pb.start();
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line ;
while((line = br.readLine()) != null)
System.out.println(line);
int exitVal = p.waitFor();
}catch(Exception e)
{ e.printStackTrace(); }
}
It doesnt goes the same way.
Several shell commands (like sed, awk and similar commands) get skipped and donot give any output at all.
Question : Is there some way to launch this script in a new terminal using java.
PS : i've found that "gnome-terminal" command launches a new terminal in shell,
But, i'm unable to figure out, how to use the same in a java code.
i'm quite new to using shell scripting. Please help
Thanks in advance
In java:
import java.lang.Runtime;
class CLI {
public static void main(String args[]) {
String command[] = {"/bin/sh", "-c",
"gnome-terminal --execute ./myscript.sh"};
Runtime rt = Runtime.getRuntime();
try {
rt.exec(command);
} catch(Exception ex) {
// handle ex
}
}
}
And the contents of the script are:
#!/bin/bash
echo 'hello!'
bash
Notes:
You'll do this in a background thread or a worker
The last command, in the shell script, is bash; otherwise execution completes and the terminal is closed.
The shell script is located in the same path as the calling Java class.
Don't overrwrite your entire PATH...
pb.environment().put("PATH", "OtherPath"); // This drops the existing PATH... ouch.
Try this instead
pb.environment().put("PATH", "OtherPath:" + pb.environment().get("PATH"));
Or, use the full directories to your commands in your script file.
You must set your shell script file as executable first and then add the below code,
shellScriptFile.setExecutable(true);
//Running sh file
Process exec = Runtime.getRuntime().exec(PATH_OF_PARENT_FOLDER_OF_SHELL_SCRIPT_FILE+File.separator+shellScriptFile.getName());
byte []buf = new byte[300];
InputStream errorStream = exec.getErrorStream();
errorStream.read(buf);
logger.debug(new String(buf));
int waitFor = exec.waitFor();
if(waitFor==0) {
System.out.println("Shell script executed properly");
}
This worked for me on Ubuntu and Java 8
Process pr =new ProcessBuilder("gnome-terminal", "-e",
"./progrm").directory(new File("/directory/for/the/program/to/be/executed/from")).start();
The previous code creates a new terminal in a specificied directory and executes a command
script.sh Must have executable permissions
public class ShellFileInNewTerminalFromJava {
public static void main(String[] arg) {
try{
Process pr =new ProcessBuilder("gnome-terminal", "-e", "pathToScript/script.sh").start();
}catch(Exception e){
e.printStackTrace();
}
}
}

Categories