I tried to use java to run some bash script and store the terminal output in a string. However, there are a lot of commands don't work in this way. It keeps showing command not found, but I can run those commands correctly in terminal, ex node --version, go --version. I guess is the path issue, but have no idea how to fix it.
Another question, when I run "python --version", it shows "Python 2.7.10" but it is in getErrorStream. Can anyone give me some hint?
public static void runscript() throws IOException {
Runtime rt = Runtime.getRuntime();
String[] commands = { "/bin/bash", "-c", "node --version" };
Process proc = null;
try {
proc = rt.exec(commands);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
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;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
}
Reply #VishalKamat comment.
when I tried using the output of "which node" as my path, which is "/usr/local/bin/node". It works!!!
But, does that mean I have to change the path when I need to get different application version info?
I thought I can easily get the info just like I do in terminal.
I try to print $PATH by java in this way
String[] commands = { "/bin/bash","-c", "$PATH" };
The error msg is :
/bin/bash: /usr/bin:/bin:/usr/sbin:/sbin: No such file or directory
Related
I'm trying to send docker commands using Java Runtime.
Commands like docker cp works very nice with the below method as well as typing directly from the terminal.
First problem is that the docker exec command works only from the terminal, not with the Java Runtime. Other docker commands like docker cp works as expected. The only problem is that I can't run commands on the container, like echoing on the container's terminal.
Also the 2nd problem is that the System.out.println(...)method in the below method, doesn't actually print anything.
private static void runCommand() throws IOException, InterruptedException {
Process proc = Runtime.getRuntime().exec(
new String[]{"/bin/sh",
"-c",
"docker exec -u 0 -it <CONTAINER_NAME> echo", "'abc'"});
BufferedReader reader =
new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
System.out.print(line + "\n");
}
proc.waitFor();
}
There is no need to run docker inside a shell. You can start the process directly.
As of Java 1.7 you can also use ProcessBuilder.inheritIO() to redirect the standard I/O of the subprocess
Below a working example that prints the output of the echo command:
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("docker", "exec" , "-it", "<CONTAINER_NAME_OR_ID>", "echo", "abc").inheritIO();
try {
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
} catch (Exception e) {
e.printStackTrace();
}
Hope this helps.
I am trying to print the output of a shell script on the console using java. When I manually run the script, I get
C:/Users/user1/Desktop/shell.sh: line 78: /usr/ucb/ps: No such file or directory
<STATUS>: Probe [ devicename ] is not running!
But, when I try to run it on my Java program, the output is not being printed on the console.
My code is:
ProcessBuilder processBuilder = new ProcessBuilder("C:/Program Files/Git/git-bash.exe","C:/Users/user1/Desktop/shell.sh");
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");
System.out.println(line);
}
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();
}
The only output I am getting is "Success". When I debugged my code, I found that the code never enters the condition
while ((line = reader.readLine()) != null)
even though, in the bash terminal, there are lines of output. Why is this happening?
I am stuck at this point and I couldn't find any other explanations for this problem. Kindly help.
You are running git-bash.exe which opens as a windows application. Although Java has access to the stdout/stderr streams of git-bash.exe, these are not necessarily the same as the stdout/err of the internal launch of your shell script within git-bash.exe.
One way to see the stdout/err of your command would be to make a java friendly version of the .sh script which launches your original sh and redirects output to a specific files which you can then access within java afterwards.
ProcessBuilder pb = new ProcessBuilder("C:/Program Files/Git/GIT-BASH.EXE","/c/Users/blah/somescript.sh");
somescript.sh:
#!/bin/sh
runtheoriginalcommand > ~/somepath.out 2> ~/somepath.err
You could also add extra args to wrapper to pass the out/err files to be used so there is no contention with any other launches or hardcoded output files.
I'm trying to run some commands on a remote machine and capture the result using Java. I have a shell script called test.sh which has following commands:
sshpass -p 'password' ssh root#host.com echo hostname
I'm running it using below java code:
public void runCommand() throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder();
boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
if (isWindows) {
builder.command("cmd.exe", "/c", "dir");
} else {
builder.command("sh", "-c", "sh test.sh");
}
builder.directory(new File(System.getProperty("user.home")));
Process process;
BufferedReader reader = null;
try {
process = builder.start();
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
String output = stringBuilder.toString();
System.out.println(output);
} finally
{
if (reader != null)
try {
reader.close();
} catch (IOException e) {
}
}
}
The command executes but I'm not getting anything in the output. If I use simple commands like echo, hostname then I'm able to get the result in output. I know of JSch which can solve the problem, but I can't use it.
When starting a Process in Java, you must consume both stdout and stderr to avoid blocking, and you should log or control both (avoid consume-to-discard). There are now easier solutions than what the linked article mentions, using ProcessBuilder.
In this instance you completely ignore error output from your command. You said your process exits with status code 127, so it probably prints on stderr so you will obtain more details about the error by using ProcessBuilder.redirectErrorStream(true).
Probably sshpass not installed, or installed but not in $PATH for your java process.
I am writing a Java application in IntelliJ IDE. The application used Rserve package to connect to R and perform some functions. When I want to run my code for the first time, I have to launch R in the command line and start the Rserve as a daemon, which looks something like this:
R
library(Rserve)
Rserve()
After doing this, I can easily access all the function in R without any errors. However, since this Java code would be bundled as an executable file, so is there a way that Rserve() is invoked automatically as soon as the code is run so that I have to skip this manual step of starting Rserve using the command line?
Here is the code for the Class I wrote to get Rserve working from Java
public class InvokeRserve {
public static void invoke() {
String s;
try {
// run the Unix ""R CMD RServe --vanilla"" command
// using the Runtime exec method:
Process p = Runtime.getRuntime().exec("R CMD RServe --vanilla");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
// System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
}
I know this question has been asked a long back . I think You have the answer. But the below answer may help others. That's why I am posting my answer.
answer:- Instead of going again and again to the R console to start Rserve. One thing you can do is you can write a java program to start Rserve.
Below code you can use in a java program to start Rserve.
https://www.sitepoint.com/community/t/call-linux-command-from-java-application/3751. This is the link where you will get the code to run a linux command from java.I have changed the command only and posting below.
package javaapplication13;
import java.io.*;
public class linux_java {
public static void main(String[] args) {
try {
String command ="R CMD Rserve";
BufferedWriter out = new BufferedWriter(new FileWriter(
new File(
"/home/jayshree/Desktop/testqavhourly.tab"), true));
final Process process = Runtime.getRuntime().exec(command);
BufferedReader buf = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line;
while ((line = buf.readLine()) != null) {
out.write(line);
out.newLine();
}
buf.close();
out.close();
int returnCode = process.waitFor();
System.out.println("Return code = " + returnCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
In Java, I want to be able to execute a Windows command.
The command in question is netsh. This will enable me to set/reset my IP address.
Note that I do not want to execute a batch file.
Instead of using a batch file, I want to execute such commands directly. Is this possible?
Here is my implemented Solution for Future Reference:
public class JavaRunCommand {
private static final String CMD =
"netsh int ip set address name = \"Local Area Connection\" source = static addr = 192.168.222.3 mask = 255.255.255.0";
public static void main(String args[]) {
try {
// Run "netsh" Windows command
Process process = Runtime.getRuntime().exec(CMD);
// Get input streams
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
// Read command standard output
String s;
System.out.println("Standard output: ");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// Read command errors
System.out.println("Standard error: ");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
Runtime.getRuntime().exec("netsh");
See Runtime Javadoc.
EDIT: A later answer by leet suggests that this process is now deprecated. However, as per the comment by DJViking, this appears not to be the case: Java 8 documentation. The method is not deprecated.
Use ProcessBuilder
ProcessBuilder pb=new ProcessBuilder(command);
pb.redirectErrorStream(true);
Process process=pb.start();
BufferedReader inStreamReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
while(inStreamReader.readLine() != null){
//do something with commandline output.
}
You can run the command with Runtime.getRuntime().exec("<command>") (eg. Runtime.getRuntime().exec("tree")). But, this will only run executables found in path, not commands like echo, del, ... But only stuff like tree.com, netstat.com, ... To run regular commands, you will have to put cmd /c before the command (eg Runtime.getRuntime().exec("cmd /c echo echo"))
public static void main(String[] args) {
String command="netstat";
try {
Process process = Runtime.getRuntime().exec(command);
System.out.println("the output stream is "+process.getOutputStream());
BufferedReader reader=new BufferedReader( new InputStreamReader(process.getInputStream()));
String s;
while ((s = reader.readLine()) != null){
System.out.println("The inout stream is " + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
This works.
Runtime#exec().