Java: Run multiple shell commands? - java

OK. I've been looking everywhere on how to execute multiple commands on a single command prompt from java. What i need to do is this, but not in command line, in code.
Execute:
cd C:/Android/SDK/platform-tools
adb install superuser.apk
..Basically i want to run adb commands from a program!!! Here is my java code so far:
MainProgram.java
public class MainProgram {
public static void main(String[] args) {
CMD shell = new CMD();
shell.execute("cmd /K cd C:/Android/SDK/platform-tools"); //command 1
shell.execute("cmd /C adb install vending.apk"); // command 2
}
}
CMD.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class CMD {
CMD() {
}
// THIS METHOD IS WHERE THE PROBLEM IS
void execute(String command) {
try
{
Process p = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
// read the output from the command
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
So what happens is...i can run the first command, but that cmd terminates and when i execute the 2nd command, a new cmd is created, hence i get an error because im not in the right directory. I tried a single string command "cmd /C cd C:/blablabla /C adb remount", but that just froze up...
Essentially, command 1 is executed and terminated, then command 2 is executed and terminated. I want it to be like this: command 1 executed, command 2 executed, terminated.
Basically i'm asking how can i run both of these commands in a row on a single command prompt???
My final target is to have a JFrame with a bunch of buttons which execute different adb commands when clicked on.

Easiest way is to make a batch file then call that from program
of course you could just say
C:/Android/SDK/platform-tools/adb install superuser.apk
there's no need to cd to a file if you name it directly
although what you are looking for is already made in ddms.bat which provides a complete visual link to adb

Create file as something.bat and set the contents to:
cd C:/Android/SDK/platform-tools
adb install superuser.apk
Then call:
Process p = Runtime.getRuntime().exec("something.bat");
all commands in the bat file are executed.

Related

Run shell script with Angular CLI commands from Java

I'm trying to run a shell script from Java (using Runtime.getRuntime().exec(cmd)). All commands in the script file seem to be running normally except the angular-cli (ng) commands.
My Java File:
System.out.println("Executing Script...");
final String[] cmd = new String[]{"/bin/bash", "test.sh"};
final Process process = Runtime.getRuntime().exec(cmd);
process.waitFor();
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s;
while ((s = reader.readLine()) != null) {
System.out.println("Script output: " + s);
}
process.destroy();
System.out.println("Script Executed.");
test.sh:
#!/bin/bash
cd ~/ &&
ng new newAngularProject &&
Outout:
Executing Script...
Script Executed.
No errors are thrown. All other commands work but for some reason, I'm unable to run ng commands. Also, I've tested the file w/o running it from Java - When I run the same script directly on the console, it works perfectly and all commands (including ng commands) work neatly. I'm running on MacOS in case you wanted to know.
Also print the error stream. You will get the error message, if it is there.
final BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((s = errorReader.readLine()) != null) {
System.out.println("error: " + s);
}
Also you can try to use absolute path of ng in your test.sh e.g. /home/my/install/node-vxxx/ng, since the process spawn by java to run your command might not get the environment variable you set in your .bashrc /.bash_aliases

Run exec file using Java on Mac

I need to start a server using bash, so I had created an UNIX shell , but I am not able to execute it with Java from Eclipse.
I tried the following code which doesn't work :
Process proc = Runtime.getRuntime().exec(./startServer);
Here is content of the startServer file :
#!/bin/bash
cd /Users/sujitsoni/Documents/bet/client
npm start
You can try the following two options.
Option 1
Process proc = Runtime.getRuntime().exec("/bin/bash", "-c", "<Abosulte Path>/startServer");
Option 2
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "<Absolute Path>/startServer");
pb.directory(new File("<Absolute Path>"));
Process proc = pb.start();
A couple Of things can go wrong:
The path to the file you have given might be wrong for eclipse it can take relative path but from the command line, it will take the absolute path.
error=13, Permission denied - If the script file doesn't have required permissions. In your scenario, that might not the case as you are not getting any error.
At last, you are executing the script by java program so the output of your script will not be printed out. In your scenario, this might be the case. You need to capture the output of script from BufferedReade and print it. ( In your case server might have started but you are not seeing the logs/output of the script.
See the code sample below for printing output.
public static void main(String[] args) throws IOException, InterruptedException {
Process proc = Runtime.getRuntime().exec("./startServer");
proc.waitFor();
StringBuffer output = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
System.out.println(output);
}

$PATH is different when I run bash from java processbuilder

When I run a bach script containing "echo $Path" command what it outputs when run by java is different from what it outputs when run from command line. It also affects other commands of my script. Why is this happening and how do I avoid?
Following is my function to run a bashscript
public static String executeCommands(File tempScript, Boolean deleteFile)
throws IOException, InterruptedException {
StringBuffer output = new StringBuffer();
try {
ProcessBuilder pb = new ProcessBuilder("bash", tempScript.toString());
pb.inheritIO();
Process process = pb.start();
process.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
return line;
} finally {
if (deleteFile == true)
tempScript.delete();
}
}
when the script contains "echo $PATH" in bashscript
output is
/usr/bin:/bin:/usr/sbin:/sbin
But when I run from commandline output is
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/scala/scala-2.11.8/bin:/Users/<user>/Installations/activator-dist-1.3.10
When we run the command from terminal it reads the environment variables from .bashrc file, but it seems eclipse does not read environment variables from .bashrc.
launch eclipse with ./eclipse -DPATH=$PATH to read from bashrc
PATH variable from
1.terminal
user#ubuntu:~$ javac SS47.java
user#ubuntu:~$ java SS47
/home/user/perl5/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/user/apache-maven-3.3.3/bin:/home/user/apache-maven-3.3.3/bin:/opt/jdk/jdk1.8.0_60/bin:/opt/jdk/jdk1.8.0_60/jre/bin:/home/user/dsc-cassandra-2.1.6/bin:/home/user/hadoop-2.6.0/bin:/home/user/hadoop-2.6.0/sbin:/home/user/android/android-studio/bin:/home/user/android/android-sdk-linux/platform-tools:/home/user/elasticsearch-2.3.5/bin:/home/user/scala-2.11.8/bin::/home/user/apache-maven-3.3.3/bin
2.eclipse with out $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
3.eclipse with PATH ./eclipse -DPATH=$PATH
/home/user/perl5/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/user/apache-maven-3.3.3/bin:/home/user/apache-maven-3.3.3/bin:/opt/jdk/jdk1.8.0_60/bin:/opt/jdk/jdk1.8.0_60/jre/bin:/home/user/dsc-cassandra-2.1.6/bin:/home/user/hadoop-2.6.0/bin:/home/user/hadoop-2.6.0/sbin:/home/user/android/android-studio/bin:/home/user/android/android-sdk-linux/platform-tools:/home/user/elasticsearch-2.3.5/bin:/home/user/scala-2.11.8/bin::/home/user/apache-maven-3.3.3/bin
As Elliott-Frisch pointed out in his comment, just call bash with the option -l which
Make[s] bash act as if it had been invoked as a login shell (see INVOCATION below). Source
This way you don't have to call Eclipse with different launch options etc. and it makes your solution independent, being able to be run without the non customized Eclipse or just bare-bone JRE.
So just edit your call ProcessBuilder like this:
ProcessBuilder pb = new ProcessBuilder("bash", "-l", tempScript.toString());

Execute ntpdate with java and get the output value

I want to execute this command within my java program and check if it was successfully executed.
sudo ntpdate -u someserver.com
I create a bash with the command
#!/bin/sh
sudo ntpdate -u omeserver.com
and execute it with java
ProcessBuilder pb = new ProcessBuilder("/updateTime");
Process p = pb.start();
p.waitFor();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
System.out.println(stdInput.readLine());
But I get no output, there are no lines in stdInput, how can I check if the command was correctly executed?
If I add for example Echo updated in the end of the bash file I get it in the stdInput, but it still don't mean that the time were updated
You'd probably get by easier when just calling sudo directly with ProcessBuilder instead of an external script. That's just redundant complexity for the task at hand.
You can feed ProcessBuilder with the whole command line, for example, like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class q39836547 {
private static String[] cmdl = { "/usr/bin/sudo",
"ntpdate",
"-u",
"some.ntp.server" };
public static void main(String[] as) throws IOException {
ProcessBuilder pb = new ProcessBuilder(cmdl);
Process p = pb.start();
BufferedReader stdin = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stderr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
try { p.waitFor(); }
catch(InterruptedException e) { }
if(p.exitValue() != 0)
System.err.println("The process was not executed successfully.");
else
System.err.println("The process ran and exited cleanly.");
stdin.lines().forEach(s -> System.out.println("STDOUT: " + s));
stderr.lines().forEach(s -> System.out.println("STDERR: " + s));
}
}
You also have to waitFor() (as you properly did) the ntpdate to finish. Otherwise you might end up reading its standard input or standard error with getInputStream() or getErrorStream() before there is any output produced into either stream.
If you comment out the try-catch-block, you'll occasionally see how the process is still running while you're trying to read its input. That is likely to happen almost every time, actually.

Show the CMD window with Java

I'm using this code to launch a .cmd file:
try {
String line;
Process p = Runtime.getRuntime().exec(myPath + "\\punchRender.cmd");
BufferedReader input =
new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
It works fine, but I want to actually see the cmd.exe window running. How can I make it show? Any help would be greatly appreciated!
Instead of running your path, try actually running cmd.exe but using the build in start command to launch a new command window. You can see the full set of command line arguments by entering the following at a command prompt:
cmd/?
start/?
in your case, you probably want to execute something like the command:
cmd /c start c:\path\to\punchRender.cmd

Categories

Resources