Weird Error JAVA process execution [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
run shell command from java
I'm trying to run a process with some arguments from inside Java and before running the particular command I print it using println.
Now the problem is from inside Java, the process is not doing good.. its sending some error on the Error Stream instead of output. But If I run the same command printed by Java on screen in console, it works perfectly.
String command="abc -def -hhij";
System.out.println(command);
Process p = Runtime.getRuntime.exec(command);
Anyone know whats going on wrong?

The Runtime.exec(String) using the StringTokenizer, which doesn't know how to process quoted text. The simplest fix is to use the exec that accepts your parameters in an array.
String[] command={ "abc", "-def", "-hhij"};
Process p = Runtime.getRuntime.exec(command);

I would try just to escape those '(' with \: '\\(' (double \ due to Java escaping rules)

Most likely the command needs the full path to the command. C:\dir\abc.exe or whatever.
If it's a script make sure it' executed by the correct shell.

Related

Passing a space separated value via shell is taking more argument then expected

I'm having difficulties to startup a java program from a shell script (bash) where nested variables are used
export MAIN_CLASS="xxxxx"
MAIN_CLASS_ARGS=("$FirstArg" "$SEC_ARG" )
CMD="java some args here ${MAIN_CLASS} ${MAIN_CLASS_ARGS[#]}"
exec $CMD
And I am passing parameter as
export FirstArg = hello
export SEC_ARG ="hi Jam"
But In my main java class I have getting 3 parameter hello, hi ,Jam. But I am expecting it to be only two. What I am missing here can anyone help me.
I have checked some of the link as
link
But not able to fix it.
When you run exec $CMD, then word splitting is performed on the contents of $CMD. It doesn't matter how the variable was built up; at this point, it's just a string which is split by the shell.
Since you appear to be using a shell with support for arrays, then one option would be to do this instead:
CMD=( java some args here "${MAIN_CLASS}" "${MAIN_CLASS_ARGS[#]}" )
exec "${CMD[#]}"
That is, build up an array of all the arguments, then use a quoted array expansion, which prevents word splitting from taking place.

java reads "*" in args[0] as the .class file

I want some code in my program to run only if the user has input the character '*' at the command-line as a command-line argument. This is the code I've used:-
//myfile.java
import java.io.*;
public class myfile {
public static void main(String[] args) {
if(args[0].equals("*")){
//do stuff
System.out.println(args[0]);//added this line to see what exactly was being passed
}
}
}
When this program is executed at the command-line by entering:-
java myfile *
the output I'm expecting to see on the screen is the asterisk character, instead the output displayed is 'myfile.class'. Where am I going wrong? Why does Java change the asterisk to the .class file?
Also, note that the program worked perfectly the first four times I executed it and then started doing this!
Thanks in advance for your help.
Where am I going wrong?
The star character needs to be quoted or escaped. Run your java program like this:
java myfile "*"
or
java myfile \*
Why does Java change the asterisk to the .class file?
It doesn't. It is your shell that is doing it. It is shell file expansion ... or "globbing" as it is also called.
Run "ls *" or "echo *" and you will see that the same thing happens.
The command terminal already replaces the asterisk and java already gets the value that you see. I'd use any other character, that has no special meaning to the command terminal or otherwise you must escape the asterisk in your command.
Actually escaping arguments on Windows and especially in cmd.exe is non-trivial. This nice article explains it in detail: Everyone quotes command line arguments the wrong way :
the takaway for your case is: surround the asterisk with quotes.
Answer to your question in the comment:
Using the escape character worked! But I still don't get why it worked without the escape character the first few times
I am not sure, but maybe you run into this behavior: It makes a difference if the pattern can be expanded or not. For example, when I pass Test* as argument, then there are 2 cases to consider:
in the current folder there is a file called Test1.txt: then your java program will get Test1.txt as argument
when there are no matching files, your program will get Test* as argument
However, I am not sure, how this would apply to your case, since you only pass *: that should only work in an empty directory.

Java Runtime.getRuntime().exec(cmd) command contain single quote

I need to use Java to rsync several files using one command
the following command works fine in shell
rsync -avrz --timeout=100 rsync://10.149.21.211:8730/'logflow/click/file1 logflow/click/file2' /home/kerrycai/puller"
but when i use the following Java code , it does not work
String cmd = "rsync -avrz --timeout=100 rsync://10.149.21.211:8730/'logflow/click/file1 logflow/click/file2' /home/kerrycai/puller";
Process p = Runtime.getRuntime().exec(cmd);
int ret = p.waitFor();
the ret value is not equal to 0 (5 in my test), and the command is not executed succeed, after some debugging , it seem the problem is caused by the single quote
So, my questions is
Can I using java to execute a shell command which has single quote in it (Pls note, the single quote is in the middle of a parameter, not start/end) ?
Can I have a shell command to rsync several files in one command , and the command does not have single(double) quotes in it ?
Note to #Chris: this combination of multiple filenames (really modified-partly-like-filenames) in one argument is indeed very unusual and even 'suspicious' for Unix in general, but is (or at least was) correct for rsync in particular.
Preface: Java Runtime.exec does NOT 'execute a shell command' (unless you explicitly run a shell and give it a command); it runs a program, with arguments. These different things are often confused because most of the shell commands used by normal users are commands to run programs, but this is one case where the difference matters. In particular quoting a space to shell causes the shell to pass a single argument to the program containing the space instead of splitting into two (or more) arguments, but the quote itself is NOT included in the argument.
First you should look at the man page (on your system or online at https://download.samba.org/pub/rsync/rsync.html) under ADVANCED USAGE. Current (and IME even moderately old) versions of rsync have a more convenient syntax with separate arguments to get multiple files, which the simple parsing used by Runtime.exec(String) can handle like this:
rsync -avrz --timeout=100 --port=8730 10.149.21.211::logflow/click/file1 ::logflow/click/file2 /home/kerrycai/puller
But if you need (or really want) to use the quoted-space form then you need to do the tokenization yourself and use the String[] overload as suggested by #EJP -- although you can still use Runtime, you don't need ProcessBuilder for this. Specifically do something along the lines of:
String[] cmdarray = {"rsync",
"-avrz",
"--timeout=100",
"rsync://10.149.21.211:8730/logflow/click/file1 logfile/click/file2",
// separated argument contains space but not single (or other) quote
"/home/kerrycai/puller" };
... Runtime.getRuntime.exec(cmdarray); ...
You're calling a somewhat large command from Java. Why not just use a shell script? Put your gnarly command in myScript.sh and then have Java invoke /bin/bash myScript.sh. Makes all the weirdness to do with string handling in Java go away.

Concise way of capturing the output of process in Java

To capture the output of process in Groovy I use the following:
"command".execute().text
I want to do the same in Java, but all responses I found contain a lot of boilerplate code involving loops, BufferedReader, Scanner, etc.:
Get Command Prompt Output to String In Java
How to run Windows commands in JAVA and return the result text as a string
java runtime.getruntime() getting output from executing a command line program
Can I do the same thing within 1-2 lines of code? Maybe Guava or Apache have something to make life simpler?
I've managed to come up with the following two-liner:
Process process = Runtime.getRuntime().exec("command")'
String output = IOUtils.toString(process.getInputStream());

egrep from Java fails while in shell succeed

I run egrep using Java Runtime.exec()
String command = "egrep \'(Success|Loading\\.\\.\\.|Loaded : READY|Found a running instance)\' "+ instance.getPath() + "/log";
Runtime.getRuntime().exec(command);
The stdout is always null and stderr shows "egrep: Unmatched ( or (". but when I copy the command to shell and run, it returns the correct value.
The solution is pretty simple: (Success|Loading\\.\\.\\.|Loaded is not a valid regex.
You can't protect white space with quotes when using Process.exec(String). Always use the versions of exec() that take an array or, even better, use ProcessBuilder.
That way, you can pass each argument as a single Java String and spaces and other special characters won't create any problems.
The single quotes should not be escaped. You don't escape them on the command line, either, do you?

Categories