Run a compound shell command from Java/Groovy - java

I got stuck trying to run a compound shell command from a Groovy script. It was one of those commands where you separate with "&&" so that the 2nd command never runs if the 1st one fails. For whatever reason I couldn't get it to work. I was using:
println "custom-cmd -a https://someurl/path && other-cmd -f parameter".execute([], new File('/some/dir')).text
The shell kept misinterpreting the command throwing errors like "custom-cmd -f invalid option" It was like it was ignoring the "&&" in between. I tried using a semi-colon as well but was not lucky. I tried using straight Java APIs Runtime.getRuntime().exec() and splitting the command into an array. I tried wrapping the command in single quotes and giving it to '/bin/sh -c' but nothing works.
How do you run a compound shell command from Java? I know I've done this in the past but I cannot figure it out today.

With groovy, the list form of execute should work:
def out = ['bash', '-c', "custom-cmd -a https://someurl/path && other-cmd -f parameter"].execute([], new File('/some/dir')).text
Of course you may want to use the consumeProcessOutput method on process, as if the output is too large, calling text may block

Try something like:
Runtime.getRuntime().exec("cmd /c \"start somefile.bat && start other.bat && cd C:\\test && test.exe\"");
Runtime.getRuntime().exec() can be used without splitting the commands into an array.
see https://stackoverflow.com/a/18867097/1410671
EDIT:
Have you tried using a ProcessBuilder? This seems to work on my OSX box:
public static void main(String[] args) throws IOException {
ProcessBuilder builder = new ProcessBuilder( "/bin/sh", "-c", "echo '123' && ls" );
Process p=null;
try {
p = builder.start();
}
catch (IOException e) {
System.out.println(e);
}
Scanner s = new Scanner( p.getInputStream() );
while (s.hasNext())
{
System.out.println( s.next() );
}
s.close();
}

Related

Execute a shell command line in Java

I tried to execute a shell command in Java, but it's not working.
I can directly run this command on Linux(Ubuntu):
/bin/sh -c 'while true ; do java -jar /home/user/workspace/TCPClientNew/WebContent/NewClient.jar 192.168.138.1 6789 ; sleep 1 ; done'
but when I do this with Java, it never executes. It always shows "Not Found".
Here is my code:
Runtime rt = Runtime.getRuntime();
Process proc;
String[] commands = {"/bin/sh","-c","'while true ; do java -jar /home/user/workspace/TCPClientNew/WebContent/NewClient.jar "+" "+host+" "+port+ " ; sleep 1 ; done'"};
proc = rt.exec(command);
Can someone tell me why it's wrong?
Thank you very much.
The single quotes in the command line are there to prevent interpretation of the third argument by the shell that runs the command line. They are not needed in Java, as there's no command line shell anymore. Just remove the single quotes.
Try to use this code might helps you.
try {
ProcessBuilder pb = new ProcessBuilder("/usr/bin/bash", "-c", "while true ; do java -jar /home/user/workspace/TCPClientNew/WebContent/NewClient.jar"+" "+host+" "+port+ " ; sleep 1 ; done");
pb.start();
} finally {
// pb.close();
}

android getRuntime().exec() with cat command

I am using the process class to run this command
/sdcard/file1.mpg /sdcar/file2.mpg > /sdcard/out.mpg
Here is how I am trying to do it:
Process processx = Runtime.getRuntime().exec(new String[] {"cat","/sdcard/file1.mpg /sdcard/file2.mpg > /sdcard/out.mpg" });
BufferedReader in = new BufferedReader(new InputStreamReader(processx.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
// Waits for the command to finish.
processx.waitFor();
The command works from terminal but not when I try the above, can anyone see why?
Redirection (>) is not the OS feature. This is a feature of shell. To make it working from java you have to run something like the following:
/bin/sh yourcommand > yourfile
i.e. in your case:
/bin/sh cat /sdcard/file1.mpg /sdcard/file2.mpg > /sdcard/out.mpg
BUT could you please explain me why are you doeing this? Do you understand that this command is exact equivalent of cp /sdcard/file1.mpg /sdcard/file2.mpg /sdcard/out.mpg that can be coded in pure java without running any command line? Unless you have special reasons go on it! Write pure java code when it is possible. It is easier to debug, support and maintain.
There's absolutely no reason to use 'cat' to do this. It's not a supported or encouraged mechanism on Android, and there's no reason to launch a new executable to do what you can easily do in java code, by reading in one file and writing it out to the other.
For the record, you are trying to do a shell redirection, and that will not work since you are not executing a shell.
im using this small code to execute "cat" command and most of shell commands:
String[] cmdline = { "sh", "-c", "cat /sdcard/file1 >> /sdcard/file2" };
try {
Runtime.getRuntime().exec(cmdline);
} catch (Exception s) {
finishAffinity();
}

Execute Unix system command from JAVA problem

I am facing a weird issue with executing a system command from JAVA code.
Actually i want to get the Mac OSX system information from my JAVA App.
For that im using
Runtime.getRuntime().exec("system_profiler -detailLevel full");
This is working fine.If i print the output,it is cool.
But i want to write this information to a plist file for future use.For that im using the -xml argument of system_profiler.like,
String cmd = "system_profiler -detailLevel full -xml > "+System.getProperty( "user.home" )+"/sysinfo.plist";
Process p = Runtime.getRuntime().exec(cmd);
Basically this should create a plist file in the current users home directory.
But this seems to be not writing anything to file.
Am i missing something here ?
My Java is more than rusty, so please be gentle. ;-)
Runtime.exec() does not automatically use the shell to execute the command you passed, so the IO redirection is not doing anything.
If you just use:
"/bin/sh -c system_profiler -detailLevel full > path/file.plist"
Then the string will be tokenized into:
{ "/bin/sh", "-c", "system_profiler", "-detailLevel", "full", ">", "path/file.plist" }
Which also wouldn't work, because -c only expects a single argument.
Try this instead:
String[] cmd = { "/bin/sh", "-c", "system_profiler -detailLevel full > path/file.plist" };
Process p = Runtime.getRuntime.exec(cmd);
Of course, you could also just read the output of your Process instance using Process.getInputStream() and write that into the file you want; thus skip the shell, IO redirection, etc. altogether.
Christian.K is absolutely correct. Here is a complete example:
public class Hello {
static public void main (String[] args) {
try {
String[] cmds = {
"/bin/sh", "-c", "ls -l *.java | tee tmp.out"};
Process p = Runtime.getRuntime().exec (cmds);
p.waitFor ();
System.out.println ("Done.");
}
catch (Exception e) {
System.out.println ("Err: " + e.getMessage());
}
}
}
If you weren't using a pipe (|) or redirect (>), then you'd be OK with String cmd = "ls -l *.java", as in your original command.
If you actually wanted to see any of the output in your Java console window, then you'd ALSO need to call Process.getInputStream().
Here's a good link:
Running system commands in Java applications

How can I call a shell script from a Java program?

I use ubuntu 10.04 with eclipse. I created a shell script, exam.sh:
#!/bin/bash
echo "Hello World"
with chmod 755 exam.sh
On the command line, I can execute ./exam.sh // ok command showing me Hello World
I want to call this exam.sh with java code, this is my java code:
public static void main(String[] args) {
Runtime r = Runtime.getRuntime();
Process p = null;
String cmd[] = {"/bin/bash","cd","/home/erdi/Desktop", ".","/","exam.sh"};
try {
p = r.exec(cmd);
System.out.println("testing...");//ok
} catch (Exception e) {
e.printStackTrace();
}
}
This doesn't function, where did I make a mistake?
Yes I know i can search by google but I didn't find an answer to my problem. It gives howTos and tutorials about this feature but I didn't find an answer.
Try this instead:
cmd[] = {"/bin/bash", "/home/ercan/Desktop/exam.sh"};
You can just invoke bash on the shell script directly. To run a command string (like cd) you would need to use the -c switch.
If you need the working directory of the script to be your Desktop, you can use another overload of Runtime.exec:
Process proc = Runtime.getRuntime().exec(cmd, new String[0], new File("/home/ercan/Desktop"));
Alternatively, the ProcessBuilder class makes executing processes a bit nicer.

Problem with starting OpenOffice service (soffice) from Java (command working in commandline, but not from Java)

I want to exceute a simple command which works from the shell but doesn't work from Java.
This is the command I want to execute, which works fine:
soffice -headless "-accept=socket,host=localhost,port=8100;urp;"
This is the code I am excecuting from Java trying to run this command:
String[] commands = new String[] {"soffice","-headless","\"-accept=socket,host=localhost,port=8100;urp;\""};
Process process = Runtime.getRuntime().exec(commands)
int code = process.waitFor();
if(code == 0)
System.out.println("Commands executed successfully");
When I run this program I get "Commands executed successfully".
However the process is not running when the program finishes.
Is it possible that the JVM kills the program after it has run?
Why doesn't this work?
I'm not sure if I'm not mistaken, but as far as I see you're generating the commands but never passing them to the "execute" method... you're executing "".
Try using Runtime.getRuntime().exec(commands) =)
I would like to say how I solved this.
I created a sh script that basically run the command of soffice for me.
Then from Java I just run the script, and it works fine, like this:
public void startSOfficeService() throws InterruptedException, IOException {
//First we need to check if the soffice process is running
String commands = "pgrep soffice";
Process process = Runtime.getRuntime().exec(commands);
//Need to wait for this command to execute
int code = process.waitFor();
//If we get anything back from readLine, then we know the process is running
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
if (in.readLine() == null) {
//Nothing back, then we should execute the process
process = Runtime.getRuntime().exec("/etc/init.d/soffice.sh");
code = process.waitFor();
log.debug("soffice script started");
} else {
log.debug("soffice script is already running");
}
in.close();
}
I also kill the soffice process by calling this method:
public void killSOfficeProcess() throws IOException {
if (System.getProperty("os.name").matches(("(?i).*Linux.*"))) {
Runtime.getRuntime().exec("pkill soffice");
}
}
Note that this only works in Linux.
I believe you aren't handling quoting correctly. The original sh command line includes double quotes to prevent the shell interpreting the semicolons. The shell strips them off before the soffice process sees them.
In your Java code the shell will never see the arguments, so the extra double quotes (escaped with backslashes) are not needed - and they are probably confusing soffice.
Here's the code with the extra quotes stripped out (and a semicolon thrown in)
String[] commands = new String[] {"soffice","-headless","-accept=socket,host=localhost,port=8100;urp;"};
Process process = Runtime.getRuntime().exec(commands);
int code = process.waitFor();
if(code == 0)
System.out.println("Commands executed successfully");
(Disclaimer: I don't know Java, and I haven't tested this!)
"/Applications/OpenOffice.org\ 2.4.app/Contents/MacOS/soffice.bin -headless -nofirststartwizard -accept='socket,host=localhost,port=8100;urp;StartOffice.Service'"
or simply escaping the quotes will work as well. We feed a command like this to an ant script that ultimately ends up in an exec call like you have above. I would also recommend restarting the process every 500 or so conversions because OOO does not properly free memory (depending on what version you are running).

Categories

Resources