Method to execute Linux command fails - java

I created the below method to execute a Linux command:
public void executeGetLogs(){
try{
Runtime rt = Runtime.getRuntime();
String [] commands = {helper.getPythonPath(), helper.getLogsMainScript(), helper.getLogsManagementUrl(), helper.getLogsManagementUrlPrefix(), helper.getLogsManagementUsername(), helper.getLogsManagementPassword(), helper.getLogsNet(), helper.getLogsStorageUrl(), helper.getLogStorageUsername(), helper.getLogStoragePassword()};
Process proc = rt.exec(commands);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
// read the output from the command
logger.debug("Standard output from execution of get_logs:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
logger.debug(s);
}
// read any errors from the attempted command
logger.debug("Standard error from execution of get_logs (if any):\n");
while ((s = stdError.readLine()) != null) {
logger.debug(s);
}
}
catch(IOException e){
logger.debug("Execution exception: " + e);
}
}
The method appears to start working correctly but then fails.
The debug shows the following output:
2017-04-21 12:27:42,391 DEBUG Standard output from execution of get_logs:
2017-04-21 12:27:44,360 DEBUG 411 new files found
2017-04-21 12:27:44,363 DEBUG Downloading files...
2017-04-21 12:27:44,446 DEBUG Standard error from execution of get_logs (if any):
What I would expect to see is
2017-04-21 12:27:44,360 DEBUG 411 new files found
2017-04-21 12:27:44,363 DEBUG Downloading files...
Downloaded 10 of 447
Downloaded 20 of 447
Downloaded 30 of 447
and so on until Downloaded 447 of 447.
I can also see that nothing gets downloaded.
My command runs when I run it in a terminal.
Is it possible something in the Java causes it to exit? One thing is that it can take a few seconds to process each block of 10. Is it possible the
while ((s = stdInput.readLine()) != null) {
logger.debug(s);
}
just sees a null because the stdInput hasn't appeared yet so it exits the loop? If so how can I fix this?

A much better way of executing code in java is ProcessBuilder. Example:
//Create the command.
ProcessBuilder command = new ProcessBuilder(helper.getPythonPath(), helper.getLogsMainScript(), helper.getLogsManagementUrl(), helper.getLogsManagementUrlPrefix(), helper.getLogsManagementUsername(), helper.getLogsManagementPassword(), helper.getLogsNet(), helper.getLogsStorageUrl(), helper.getLogStorageUsername(), helper.getLogStoragePassword());
//Will show console output in java console.
command .inheritIO();
//Launches de command.
Process process= command .start();
Hope it helps.

Got to the bottom of it. I need to wait for the process to end. This can be done with the below code:
proc.waitFor();
My method now looks like this:
public void executeGetLogs(){
try{
Runtime rt = Runtime.getRuntime();
String [] commands = {helper.getPythonPath(), helper.getLogsMainScript(), helper.getLogsManagementUrl(), helper.getLogsManagementUrlPrefix(), helper.getLogsManagementUsername(), helper.getLogsManagementPassword(), helper.getLogsNet(), helper.getLogsStorageUrl(), helper.getLogStorageUsername(), helper.getLogStoragePassword()};
Process proc = rt.exec(commands);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
try{
proc.waitFor();
}
catch(InterruptedException e){
logger.debug("Interrupted Exception : " + e);
}
BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
// read the output from the command
logger.debug("Standard output from execution of get_logs:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
logger.debug(s);
}
// read any errors from the attempted command
logger.debug("Standard error from execution of get_logs (if any):\n");
while ((s = stdError.readLine()) != null) {
logger.debug(s);
}
}
catch(IOException e){
logger.debug("Execution exception: " + e);
}
}

Related

How to handle interactive commands using runtime.getRuntime?

I have to execute a command from Java program on Unix platform.
I am using Runtime.getRuntime() for it.
However, the problem is that my command is interactive and asks for certain parameters at runtime. For e.g., the command is createUser. It asks for userName as the runtime.
bash-4.1$ createUser
Enter the UserName:
How can I handle such scenario so that the user name is entered at runtime from Java program?
try {
Process proc;
proc = Runtime.getRuntime().exec(cmd, envp);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
// read the output from the command
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
sb.append(s);
}
// read any errors from the attempted command
while ((s = stdError.readLine()) != null) {
System.out.println(s);
sb.append(s);
}
} catch (Exception e) {
e.printStackTrace();
sb = null;
}
I heard that it can be done through expect. But How can I do it in Java?
Get also the standardOutput from proc. All you write in that standardOutput goes to the command
Send the username to standardOutput and don't forget to send the \n too.
You can check what was the last line of input steam and when you detect the prompt for user input input write to the output steam your value.
try {
Process proc;
proc = Runtime.getRuntime().exec(cmd, envp);
final BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
final PrintWriter stdOutput = new PrintWriter(proc.getOutputStream());
// read the output from the command
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
if (s.equals("Enter your username")) {
stdOutput.println("MyUsername");
stdOutput.flush();
}
sb.append(s);
}
} catch (final Exception e) {
e.printStackTrace();
sb = null;
}
(removed the error stream for simplicity)
Note that this works only if the prompt ends with a new line.
If the prompt has no new line (eg. Username: <cursor here>) you can try just writing the value at the start:
...
final PrintWriter stdOutput = new PrintWriter(proc.getOutputStream());
stdOutput.println("MyUsername");
stdOutput.flush();
...
But if the the command clears the buffer this will no work, in that case (rare case) you have to change the way you read from the stream (eg. instead of lines, read bytes)

java run bash script, command not found

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

Opening cmd and waiting user input in cmd and exec commands from java

My problem is, after opening cmd from java code, i want user to be able to input like in c++ ms dos applications. When user writes sth such as "dir" or "cd..", i want to execute these codes by java.
The problem is for every command java re-opens cmd again. Also i cannot execute commands. My cmd start code is below ;
final ArrayList<String> commands = new ArrayList<>();
commands.add("cmd.exe");
commands.add("/C");
commands.add("start");
ProcessBuilder pb = new ProcessBuilder(commands);
Process process = pb.start();
Here's some cleaned up code from How to open the command prompt and insert commands using Java?
public static void main(String[] args) {
try {
String ss = null;
Runtime obj = null;
Process p = Runtime.getRuntime().exec("cmd.exe");
//write a command to the output stream
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
writer.write("dir");
writer.flush();
//Get the input and stderror
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
System.out.println("Here is the standard output of the command:\n");
while ((ss = stdInput.readLine()) != null) {
System.out.println(ss);
}
System.out.println("Here is the standard error of the command (if any):\n");
while ((ss = stdError.readLine()) != null) {
System.out.println(ss);
}
} catch (IOException e) {
System.out.println("FROM CATCH" + e.toString());
}
}

Runtime.getRuntime failed to get output same time but later

I'm currently making firefox addon development GUI tool using Java. However I am stuck when trying to get output of a .bat file.
When I run .bat file using java I can see the output, but there are 3 commands written in the bat file. When first command executes I can get the output simultaneously. But when it execute second command output not coming. And when .bat file exist I get all the output which didn't come simultaneously.
I'm getting output immediately when it execute:
call "C:\mozilla-build\addon-sdk-1.16\bin\activate.bat
But I'm not getting output simultaneously for following command:
call cfx run
But I know it's executing because firefox window pops up. I get all the output suddenly when I execute proc.destroy();
This is my bat file:
#echo off
call %1
cd C:\Users\Madhawa.se\Desktop\workingfox\beauty
call cfx run
pause
This is my Java code:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"C:\\Users\\Madhawa.se\\Desktop\\workingfox\\runner\\foxrun.bat", "C:\\mozilla-build\\addon-sdk-1.16\\bin\\activate.bat"};
proc = rt.exec(commands);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
// read the output from the command
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
proc.waitFor();
System.out.println("success");
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
t.start();
How to get output immediately and why it acts differently for this command?
i was able to fix it using process builder instead of runtime.exec .and inheriteIo doesn't work .it blocks the realtime output
Thread t = new Thread(new Runnable() {
private String s;
#Override
public void run() {
try {
Component selectedComponent = jTabbedPane2.getSelectedComponent();
if (selectedComponent instanceof MyTextArea) {
String response = "";
System.out.println("yes");
MyTextArea temptextarea = (MyTextArea) selectedComponent;
String xpiPath = new File(temptextarea.getNameX()).getParentFile().getPath();
String[] commands = {"C:\\Users\\Madhawa.se\\Desktop\\workingfox\\runner\\foxrun.bat", "C:\\mozilla-build\\addon-sdk-1.16\\bin\\activate.bat
ProcessBuilder process = new ProcessBuilder(commands);
process.redirectErrorStream(true);
Process shell = process.start();
//shell.waitFor();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(shell.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(shell.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:" + 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("w:" + s);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}

How to Execute Windows Commands Using Java - Change Network Settings

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().

Categories

Resources