Execute Unix system command from JAVA problem - java

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

Related

Run a compound shell command from Java/Groovy

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();
}

Redirecs with /bin/bash from Java Runtime exec()

I'm trying to use a redirect in a command executed with the exec()-method of java.lang.Runtime on Ubuntu 14.04
public static void main(String[] args) throws IOException, Exception {
Runtime runtime = Runtime.getRuntime();
String command = "echo bla > bla.txt";
System.out.println("Command : " + command);
Process process = runtime.exec(command);
printLines(" stdout", process.getInputStream());
printLines(" error", process.getErrorStream());
process.waitFor();
System.out.println("ExitValue : " + process.exitValue());
}
private static void printLines(String name, InputStream ins) throws Exception {
try(Stream<String> lines = new BufferedReader(new InputStreamReader(ins)).lines()) {
lines.forEach(line -> System.out.println(name + " : " + line));
}
}
The output is:
Command : echo bla > bla.txt
stdout : bla > bla.txt
ExitValue : 0
So bla > bla.txt is written to stdout but of course there is no redirect to bla.txt.
Perhapes shell redirects are not possible in a simple exec().
So I tried to change the command = "/bin/bash -c 'echo bla > bla.txt'" to use the whole echo and redirect as a parameter to /bin/bash.
With this I get the result:
Command : /bin/bash -c 'echo bla > bla.txt'
error : bla: -c: line 0: unexpected EOF while looking for matching `''
error : bla: -c: line 1: syntax error: unexpected end of file
ExitValue : 1
Of course /bin/bash -c 'echo bla > bla.txt'works fine on Ubuntu and creates the desired file.
I found no place where I could set the single quotes to get a satisfying result, and I also tried with all kinds of escape characters to escape the spaces or the redirect (>).
It works if I use a command array like
String cmdArray[] = {"/bin/bash", "-c", "echo bla > bla.txt"};
Process process = runtime.exec(cmdArray);
, but it has to be a single string because the entire command has to be build somewhere else.
I surely know
that there are better ways to write strings to files,
that it may be a bad idea to execute commands build somewhere else,
and so on ...
I'm just curious why this does not work.
The cause is that exec uses simple StringTokenizer with any white space as a delimiter to parse the actual command. Therefore it's portable as it does work nowhere when you pass something complex :-)
The workaround you chose is correct way, portable and most of all safest asyou ddon't need to escape if the command contained for example quotes etc.
String command = "echo bla > bla.txt";
Process process = runtime.exec(command);
The > blah.txt text in your command is shell syntax to redirect standard output. It's implemented by shells like sh or bash.
Runtime.exec() doesn't use a shell to run commands. The way it launches commands is described here and here. Basically, it uses its own logic to split the command string into arguments at spaces, then directly executes the resulting command.
If you want to invoke a command which should be interpreted as a shell command, you need to explicitly invoke a shell:
String[] command = { "/bin/bash", "-c", "echo bla > bla.txt" };
Process process = runtime.exec(command);

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();
}

How can I implement and use command prompt commands through the java and see results in java?

How can I implement and use command prompt commands through the java and see results in java? The command prompt commands are following:
cd Desktop\nikto-2.1.4
nikto.pl -h www.cirt.net -ssl .
What I should do in order to be able to use those commands in java and to see results?
I would use ProcessBuilder to set the current directory and run the second command using cmd.exe. I would combine the error and output and read the output into your Java program.
A simple way to run comands is by using Process object.
String[] commands = { "cd Desktop\nikto-2.1.4", "nikto.pl -h www.cirt.net -ssl ." }
Process process = Runtime.getRuntime().exec( commands );
try {
InputStream is = process.getInputStream();
try {
//.... do something
}
finally { is.close(); }
}
finally { process.destroy(); }
Now handling all of these different streams can be messy, thus -> java.lang.ProcessBuilder suggested by Mr. Lawrey. It is a utility class provided by JVM intended to simplify usage of Process object. It would make given example more tolerable.
The following code will display the output of nikto.pl -h www.cirt.net -sslb, allowing you to capture and manipulate it.
cd Desktop\nikto-2.1.4
for /f "tokens=*" %%x in ('nikto.pl -h www.cirt.net -sslb') do echo %%x

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.

Categories

Resources