How to use Java ProcessBuilder to execute ./filename in linux - java

I'm currently using ProcessBuilder to run some file like test.out.
Here is some of my code
ArrayList cmd = new ArrayList();
cmd.add("sudo");
cmd.add("./test.out");
String s = "";
try{
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.directory(new File("/myPath"));
pb.redircErrorStream(true);
Process p = pb.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferReader br = new BufferReader(isr);
String line = "";
while((line = br.readLine()) !=null)
{
s+=line;
}
System.out.println(s);
}
I output the path which is correct("/myPath").
when I remove line
`cmd.add("sudo")`
the output will give me a String:
oneoflib:must be root. Did you forgot sudo?
But once I add
cmd.add("sudo");
there is nothing output.
Is there anyone whats wrong with it?
I can run sudo ./test.out from terminal which works fine.
I'm using eclipse BTW.
Thank you very much.

I guess that getting the error stream from the process could be beneficial here to help debug the problem.
This should help, consider the following bash script and let's call it yourExecutable. Let's also assume that it has all the proper permissions:
if [ "$EUID" -ne 0 ]
then echo "Please run as root"
exit
fi
echo "You are running as root"
When run without sudo it prints "Please run as root" other wise it prints "You are running as root"
The command, ie first argument in your list should be bash, if that is the shell you are using. The first argument should be -c so the commands will be read from the following string. The string should be echo <password> | sudo -S ./yourExecutable. This isn't exactly the best way to send the password to sudo, but I don't think that is the point here. The -S to sudo will prompt for the password which is written to stdout and piped over to sudo.
public static void main(String[] args) throws IOException {
Process process = new ProcessBuilder("bash", "-c", "echo <password> | sudo -S ./yourExecutable").start();
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String string;
while((string = errorReader.readLine()) != null){
System.out.println(string);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
while((string = reader.readLine()) != null){
System.out.println(string);
}
}
Output on my machine looks like:
Password:
You are running as root

Related

Sending 'exec' commands to Docker container using Java

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.

Difference when executing linux command from terminal and java runtime process

I'm looking a way to write running log of python which is executed by java app via script.
Let's say my script is:
import time
for x in range(120):
print("Running ", x)
time.sleep(1)
Here is my current solution:
Trigger script using java
String cmd = "python script.py";
var process = Runtime.getRuntime().exec(cmd, null, new File(sandboxPath));
Write log to new file:
String traceLogCmd = String.format("strace -p %s -s 9999 -e trace=write -o output.txt", process.pid());
Runtime.getRuntime().exec(traceLogCmd, null, new File(sandboxPath));
Now the problem is output.txt only has content whenever the python script is done executing so that I cannot tailf the output file.
Meanwhile if I execute python script.py and strace command dirrectly from terminal, the output is exactly what I expected.
Can someone correct me if I did something wrong or have a another way to get python log?
Thanks in advance.
Use ProcessBuilder instead of Runtime.exec(). More details: When Runtime.exec() won't
The following code will append to StringBuilder object output of the script sb.append(line);. It would not be difficult to write that content to a file.
Process p = new ProcessBuilder("sh", "-c", "python", "path-to-your-script").start();
String result = getCommandResult(p.getInputStream());
private static String getCommandResult(InputStream stream) throws IOException {
StringBuilder sb = new StringBuilder();
try (InputStreamReader isr = new InputStreamReader(stream);
BufferedReader in = new BufferedReader(isr)) {
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
}
return sb.toString().trim();
}

java exec attempting to untar a file

I have been trying to untar a .tbz file without a lot of success in a java app. I have now decided to try and hit the command line to get the job done, and it currently doesn't through any errors but it doesn't untar the file, either. Can anyone see an issue with this?
String[] cmd = { "tar", "-xjf", "/var/tmp/filename.tbz"};
Process p =Runtime.getRuntime().exec(cmd, null);
EDIT, this works:
List<String> commands = new ArrayList<String>();
commands.add("tar");
commands.add("-xvjf");
commands.add("/var/tmp/filename.tbz");
ProcessBuilder pb = new ProcessBuilder(commands);
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String readline;
while ((readline = reader.readLine()) != null) {
System.out.println(readline);
}
What is a cd command doing there in the middle? Perhaps you meant this:
String[] cmd = { "tar", "-xjf", "/var/tmp/filename.tbz"};
If instead of the above, you really want to do this:
cd /var/tmp
tar -xjf filename.tbz
In this case you can use ProcessBuilder.

Running different .exe program from java program

I got stuck while trying to run bfgminer.exe -o bla.bla.com -u <nick> -p <passwd> -S auto -d all
I tried a number of ways to run this executable, but I can't get it to work:
public static void runCmd(){
try{
ProcessBuilder builder = new ProcessBuilder("cmd.exe","/c", "cd \"C:\\Users\\pawisoon\\bfgminer-3.10.0-win64\" && bfgminer.exe -o bla.bla.com -u <user> -p
<pswd> -S auto -d all");
builder.redirectErrorStream(true);
Process pd = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(pd.getInputStream()));
String line;
while (true) {
line = r.readLine();
if (line == null) { break; }
System.out.println(line);
}
}
catch(IOException e){
}
}
This is what I got from console in Eclipse:
'bfgminer.exe' is not recognized as an internal or external command,
operable program or batch file.
Please help me how to solve this problem :/
Thanks a lot for your answers ! I combined your advises and it worked. Here is code :
public static void runCmd(){
File f = new File("C:\\Users\\pawisoon\\bfgminer-3.10.0-win64");
try{
ProcessBuilder builder = new ProcessBuilder("cmd.exe","/c","start","bfgminer.exe", "-o", "bla.bala.com", "-u", "user", "-p", "lelelel", "-S", "auto", "-d", "all");
builder.directory(f);
builder.redirectErrorStream(true);
Process pd = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(pd.getInputStream()));
String line;
while (true) {
line = r.readLine();
if (line == null) { break; }
System.out.println(line);
}
}
catch(IOException e){
}
}
From what I see, you try to execute
cd C:\Users\pawisoon\bfgminer-3.10.0-win64\
And then
bfgminer.exe -o bla.bla.com -u -p -S auto -d all
because I imagine bfgminer.exe is in the suppposed actual repertory (C:\Users\pawisoon\bfgminer-3.10.0-win64)
But actually I'm not sure your two cmd commands are correctly executed (I mean: I'm not sure the repertory is kept as a reference for the execution of the second command)
So why don't just try to execute
C:\Users\pawisoon\bfgminer-3.10.0-win64\bfgminer.exe -o bla.bla.com -u -p -S auto -d all
(no cd and full path to the executable)
Or check out #ginz comment and try to launch the executable directly (not using cmd) if you don't especially want to use cmd.exe

ProcessBuilder with multiple commands

I'd like to execute multiple commands with ProcessBuilder. I want to avoid using script files, only hardcoded strings in Java.
This is the current file that I'd like to execute.
#!/bin/sh
if [ -e /tmp/pipe ]
then
rm /tmp/pipe
fi
mkfifo /tmp/pipe
tail -f /dev/null >/tmp/pipe & # keep pipe alive
cat /tmp/pipe | omxplayer $1 -r &
Now, this is my current code.
private static final String[][] commands = {
{"rm", "-f", "/tmp/airpi_pipe"},
{"mkfifo", "/tmp/airpi_pipe"},
{"tail", "-f", "/dev/null", ">", "/tmp/airpi_pipe"}
};
public static void main(String[] args) throws IOException {
for (String[] str : commands) {
ProcessBuilder pb = new ProcessBuilder(str);
pb.redirectErrorStream(true);
Process process = pb.start();
InputStream is = process.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
System.err.println("next one");
}
}
Obviously, the tail command doesn't work in my ProcessBuilder. I haven't even tried with cat /tmp/pipe | omxplayer $1 -r &.
So, my question is, how could I manage to execute the content of my sh script with ProcessBuilder, but only with hardcoded commands (no script file), as I'm trying to do?
Thank you.
UPDATE
I had to use new ProcessBuilder("/bin/sh", "-c", "<commands>"); to make it work!

Categories

Resources