I'm trying to edit a file from CLI. I'm executing the nano command (I know that command will always be available); when I execute it, I can see nano's output but I cannot interact with it. How can I pass user input to the command? Do you have a better idea to easily edit a file from within my Java app?
This is my code:
String command = "nano /tmp/163377867.txt ";
try {
Process process = Runtime.getRuntime().exec(command);
InputStream inputStream = process.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
The problem with Java's Runtime.exec is that it connects stdin and stdout to "pipes," while many console programs need a TTY device.
One way to solve this problem is to make the Java program's controlling terminal available to the program you execute:
Process proc = Runtime.getRuntime().exec(new String[]{
"sh", "-c", command+" </dev/tty >/dev/tty"});
proc.waitFor(); // wait for user to finish editing the file
Related
my java method looks like this:
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
String line = "";
Process proc;
try {
proc = Runtime.getRuntime().exec(command);
InputStream inputStream = proc.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
proc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
If I send small commands like "ls -l" it executes the command and print the results. But I need this function to read the output from an application wich will run for days and it will print frequently output while running. So I can't wait until the application is "done", I need the output in realtime. Anyone knows how to print the output without delay? thanks for help..
The simplest way is to redirect the output of the command directly to a file:
ls -l > ./ls.output
In this case you don't need to wait the end of the command. It will be the operating system to handle the output redirection to a file.
If you need also to write the output for the error you need a command like the following:
ls -l > ./ls.output 2> ./ls.err
where ./ls.output is the normal output and ./ls.err is the output for errors
I have a computer algebra program (called Reduce) that works in the shell in an interactive manner: launch Reduce in the shell, then you can define variables, compute this and that, and what not. Reduce prints the output into the shell. My idea is that I want to build a frontend for this text-based program that evaluates its output and converts it into a nice LaTeX style formula. For this I want to use Java.
I can start Reduce via exec(). But how can I emulate text input to the opened shell, and how can I read back what Reduce writes into the shell?
Thanks
Jens
Edit 1: Current Code
// get the shell
Runtime rt = Runtime.getRuntime();
// execute reduce
String[] commands = {"D:/Programme/Reduce/reduce.com", "", ""};
Process proc = null;
try {
proc = rt.exec(commands);
} catch (Exception e) {
System.out.println("Error!\n");
}
// get the associated input / output / error streams
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedWriter stdOutput = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
try {
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
try {
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
}
You need to get the streams associated with the process including the InputStream, OutputStream, and ErrorStream. You then can send messages to the process via the OutputStream and then read info from the process via the InputStream and the ErrorStream.
From some code of mine:
final ProcessBuilder pBuilder = new ProcessBuilder(TEST_PROCESS_ARRAY);
final Process proc = pBuilder.start();
procInputStream = proc.getInputStream();
errorStream = proc.getErrorStream();
errorSBuffer = new StringBuffer();
streamGobblerSb = new StreamGobblerSb(errorStream, "Autoit Error", errorSBuffer);
new Thread(streamGobblerSb).start();
final Scanner scan = new Scanner(procInputStream);
You may want to look into using the Process class.
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
I believe you may be able to start the process, and then use getOutputStream() to feed commands into the process.
While this is not strictly an answer, I discovered that it is more convenient for me to stick with PHP's function proc_open(). That way I can include the output directly in the frontend and do not need to worry about the communication between my Java program and the html frontend.
For everybody who wants to stick to the Java method: the article http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html is a good reference.
I want to execute a command mspview -r "C:\\Users\\SS\\Desktop\\phantomjs-1.9.2-windows\\image.tif". How can I do it via Java code? I am trying to do this with a batch file. The same command when I run with the help of RUN. I am getting correct output. I have executed a .exe program with the help of a batch file with the following code C:\Users\SS\Desktop\phantomjs-1.9.2-windows\phantomjs.exe.
You're basically asking how to run shell commands in java, right?
Runtime.getRuntime().exec("whatever system call you want");
You need to use ProcessBuilder
Process process = new ProcessBuilder(
"C:\\PathToExe\\exe.exe","param1","param2").start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
System.out.printf("Output of running %s is:", Arrays.toString(args));
while ((line = br.readLine()) != null) {
System.out.println(line);
}
code that is already found on stackoverflow
Execute external program in java
This is a frustrating problem. I'm running the following Java code:
try {
String query = someQuery, input = someInput;
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", query); // Windows
Process p = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
try
{
// Input to the query
OutputStream os = p.getOutputStream();
os.write(input.getBytes());
os.flush();
os.close();
} catch (IOException e)
{
}
System.out.println("STDIN : \n");
while ((s = stdInput.readLine()) != null)
{
System.out.println(s);
}
System.exit(0);
} catch (IOException e)
{
e.printStackTrace();
}
query is a piped command. Each sub-command within query is a unix-like API call (proprietary : Sirsi Unicorn API if anyone's interested); also it is a database call. The windows command prompt can accomodate these API calls.
PROBLEM:
If I try piping 2 database commands, the program runs successfully, but if I pipe 3 database commands, the program just hangs. If these same commands are run on cygwin, the program works fine. Interestingly, if I break the 3 pipe command into two separate commands, the program runs fine.
QUESTION:
My question is- is there a pipe buffer problem on the windows command line? Are there instances where piping on windows won't work? Can piping time out?
At this point, any info is appreciated.
I am running a Shell script using cygwin.
Process p;
InputStream in;
BufferedReader br;
String line;
String cmd;
cmd = "D:/cygwin/bin/bash -c '/bin/test/app.sh" +three_ltr_id+""+mon_code+""+year_code+""+part_no+""+version_no+" '";
System.out.println("EXECUTING: " + cmd);
p = Runtime.getRuntime().exec(cmd);
in = p.getInputStream();
p.waitFor();
br = new BufferedReader(new InputStreamReader(in));
System.out.println("OUT:");
while ((line = br.readLine()) != null) {
System.out.println(line);
System.out.println("SCRIPT EXECUTED PROPERLY");
This is showing EXECUTING and the commands that I passed to script.
If I go inside D:/cygwin/bin/test folder and run the same command it works.
When I run the same command at the command line it won't work.
You need to start reading the input from p.getInputStream() immediately, and keep reading it until there is no more. On Windows, there is little or no buffer in the pipe, and the process will hang once it is filled.
Same is true for the error stream. You could launch threads to read both streams, or there's an option in the way you launch processes to combine regular output and errors, and you can just read them from there.