/bin/sh -c not working with process builder - java

I am trying to run the following command via process builder:
ls -lrt my-directory | tail -1
I am using bin/sh -c when passing it in but cannot get it to work any way I try.(my custom directory depends on the function and is passed in as a string)
process builder("/bin/sh", "-c", "ls -lrt ", customDir, " | tail -1");
This gives the contents of the directory I am running the program out of. It's as if I simply typed ls (not even ls -lrt).
Both of
String temp = "ls -lrt " + customDir + " | tail -1";
process builder("/bin/sh ", "-c " temp);
String temp = "ls -lrt " + customDir;
process builder("/bin/sh ", "-c " temp, " | tail -1");
say that the directory doesn't exist even though I know it does. Removing /bin/sh -c simply gives me an error saying it couldn't understand the ls -lrt command which I understand. But I simply have no idea how to get it to produce the actual results I would get if I typed this command in seperately.
edit: the problem is not because of how I am calling process builder. I send the content to another function which calls process builder properly and relays its output.For simplicity, I just said process builder (...) in the examples.

Related

Executing mv command with Java.exec();

I am trying to move an file via the linux mv command.
I have following code:
processBuilder.command("/bin/sh", "-c", "\"mv", "\"" + rawOutput + "/" + dir + "/build/libs/*\"", "\"" + startDir + "/test.jar\"\"");
During execution it translates to
/bin/sh -c "mv "/home/test/update/Test-test-23afi369890Ajk/build/libs/*" "/home/test/test.jar""
While this command executes perfectly via the command line, it fails during execution of the jar.
Following error is given:
"/home/test/update/Test-test-23afi369890Ajk/build/libs/*": 1: "/home/test/update/Test-test-23afi369890Ajk/build/libs/*": Syntax error: Unterminated quoted string
Thanks in advance!
Here's the shell command you want to execute:
mv /home/test/update/Test-test-23afi369890Ajk/build/libs/* /home/test/test.jar
Here's the Java concatenation that builds this shell command in Java (you should print and copy-paste it to a shell to verify it):
String myCmd = "mv " + rawOutput + "/build/libs/* " + dir + "/test.jar";
Here's how you can run it in a shell:
processBuilder.command("/bin/sh", "-c", myCmd);
This gives the following argument list:
/bin/sh
-c
mv /home/test/update/Test-test-23afi369890Ajk/build/libs/* /home/test/test.jar
And for completeness, here's how you should have designed it, with a static command string and passing in the arguments as separate parameters to avoid shell injection:
String myCmd = "mv \"$1\"/build/libs/* \"$2\"/test.jar";
processBuilder.command("/bin/sh", "-c", myCmd, "_", rawOutput, dir);
Whose argument list is:
/bin/sh
-c
mv "$1"/build/libs/* "$2"/test.jar
_
/home/test/update/Test-test-23afi369890Ajk
/home/test
(the _ becomes $0, i.e. the script's filename for use in error messages and similar)
During execution [my attempt] translates to
/bin/sh -c "mv "/home/test/update/Test-test-23afi369890Ajk/build/libs/*" "/home/test/test.jar""
I don't know how you reached this conclusion. The actual argument list it expands to is:
/bin/sh
-c
"mv
"/home/test/update/Test-test-23afi369890Ajk/build/libs/*"
"/home/test/test.jar""
This corresponds to the following shell command which probably fails with the same error messages as your Java program (if you're not suppressing stderr):
$ /bin/sh -c '"mv' '"/home/test/update/Test-test-23afi369890Ajk/build/libs/*"' '"/home/test/test.jar""'
"/home/test/update/Test-test-23afi369890Ajk/build/libs/*": 1: Syntax error: Unterminated quoted string

Execute command from java which might include spaces

I am trying to execute the following command from a java program:
java -jar /opt/plasma/fr.inria.plasmalab.plasmalab-1.3.4.jar -t -a montecarlo -A"Total samples"=1000 -m models/translated/plasma/NaCl2.rml:rml --format csv -r models/translated/plasma/NaCl2.bltl:bltl
with the following code:
String totalSample = "-A\"Total samples\"=1000";
String mcCommand = "java -jar " + MChecker.getAppPath() + " -t "
+ "-a " + "montecarlo " + totalSample
+ " -m " + mcModelRelPath + ":rml " + "--format " + "csv "
+ "-r " + customQueryRelPath + ":bltl";
Process process = Runtime.getRuntime().exec(mcCommand);
int errCode = process.waitFor();
//then get the output, and error
But it results in the following error:
Wrong parameter description : Dynamic parameter expected a value of the form a=b but got:"Total
I ran the same command in a terminal and it worked without any problem. But when I create the command in Java and try to invoke the tool it does not work.
I think it's confused because of the totalSample parameter which includes a space. What I did next was to put "\ " space escape in paramater(String totalSample = "-A\"Total\\ samples\"=1000";), but it still refused to accept it. It gave the following error:
Wrong parameter description : Dynamic parameter expected a value of the form a=b but got:"Total\
Then I run the same parameters with the ProcessBuilder object, like the following:
String[] mcCommand = {"java", "-jar", MChecker.getAppPath(), "-t",
"-a", "montecarlo",totalSample, "-m",
mcModelRelPath + ":rml", "--format", "csv", "-r",
customQueryRelPath + ":bltl" };
ProcessBuilder pb = new ProcessBuilder(mcCommand);
Process process = pb.start();
process.waitFor();
But it still did not work and threw some custom exceptions.
I am currently out of options -- do you have any idea why this command does not work with Java, when it works just fine from the terminal interface?
BTW: I ran the same code on Windows it worked perfectly, but I have to run this code on Ubuntu OS.
Many Thanks
It was weird that, Java Process and ProcessBuilder classes could not pass the parameters properly. I don't know why, but since I was able to execute the command from terminal. I decide to call the terminal first and then execute the command. Therefore, I changed my command as following
String mcCommand[] = {
"/bin/sh",
"-c",
"java -jar /opt/plasma/fr.inria.plasmalab.plasmalab-1.3.4.jar -t -a montecarlo "+totalSample+" -m models/translated/plasma/NaCl2.rml:rml --format csv -r models/translated/plasma/NaCl2.bltl:bltl" };
Despite it is platform dependant solution, currently it is ok for me.
Don't add extra quotes for Total samples when using ProcessBuilder:
ProcessBuilder pb = new ProcessBuilder("java", "-jar", MChecker.getAppPath(), "-t",
"-a", "montecarlo", "-ATotal samples=1000",
"-m", mcModelRelPath + ":rml", "--format", "csv",
"-r", customQueryRelPath + ":bltl");
//...

Can't execute Shellscript successfully using getruntime.exec()

I have written a code to execute a script from java :
String wrapper_script=homedir+"/blast_distribute.sh "+" --seqs="+seqs+" --i="+formobj.getUpFile().getFileName()+" "+formobj.getSelected_program();
script_exec=Runtime.getRuntime().exec(wrapper_script);
This works perfect for me as command is executed successfully. Now I need to run this command as other user so I need to execute a command in a format like :
su username -c 'command'
SO I have edited above script_exec string as :
String wrapper_script1="su - "+username+" -c "+"'"+wrapper_script+"'";
I have printed wrapper_script1 which diplays:
su - abhijeet -c '/home/abhijeet//blast_distribute.sh --seqs=1562
--i=mPS_0.contigs.fasta'
If I run same command directly on Linux,It works exactly as I need.But When I am running through :
script_exec=Runtime.getRuntime().exec(wrapper_script1);
It does't work properly ,In my error stream I get error as
su: unrecognized option '--seqs=1562' Try `su --help' for more
information.
I have tried a lot but could't resolve the issue.What can be the reason for this issue?
You should use multiple parameters run for this:
Runtime.getRuntime().exec(new String[] {"su", "-", username, "-c",
homedir + "/blast_distribute.sh " + " --seqs=" + seqs + " --i=" + formobj.getUpFile().getFileName() + " " + formobj.getSelected_program()
});
You're getting the error, because ' is not treated here as a enclosing characters, but as a parameters for su command.
Let's look into details. When you type into console some command like su - jsmith -c 'aba --cabga', what you're doing is: "run command su with such an arguments: -, jsmith, -c, aba --caba (one argument for multiple words)".
The same thing you should do in your Java code. There's special command in Java API for running the concrete command with concrete arguments instead of parsing line as shell do: Runtime.exec(String[]): the first argument is command, the next are the arguments. That's what we do in this code block.

jmap -histo:live output is empty

Sometimes when I execute a command:
"$JAVA_HOME/bin/jmap -histo:live " + pid + " > " + fileName
I get an empty(blank) file.
Why this may happen?
P.S. This is using in autotest (test on memory leaks).
With option -F (forced) I get histogram, but it includes non-live objects.
Thx, for any help.

Using Java's ProcessBuilder to run SoX

I am running SoX from java using a ProcessBuilder to trim a wav file. I am sure I should be able to run SoX, cause in the other JUnit tests, I manage to successfully run the following commands:
sox/sox --version
sox/sox --i -r test/test.wav
sox/sox --i -D test/test.wav
sox/sox --i -b test/test.wav
sox/sox --i -c test/test.wav
but when I try to trim a file as in the following:
sox/sox -V3 "/Users/username/workspace/Thesis Corpus Integrator/test/test.wav" -b 16 "/Users/username/workspace/Thesis Corpus Integrator/test/newWaveFile.wav" channels 1 trim 0:00:00.000 =0:00:30.000
it throws an IOException with the error: error=2, No such file or directory. I tried running the command on a terminal, and it worked without a problem. If it matters, I ran it through a JUnit test from eclipse, on a macbook.
Here's the code I used to build it in ProcessBuilder:
StringBuilder command = new StringBuilder(soxCommand) // soxCommand resolves to sox/sox, and is used in all the other tests without any problems
if (WavCutter.getMetadata(srcFile.getAbsolutePath(),
MetadataField.SAMPLE_RATE) != 16000) {
command.append(" -V3");
command.append(" -G");
command.append(" \"" + srcFile.getAbsolutePath() + '\"');
command.append(" -b 16");
command.append(" \"" + destFile.getAbsolutePath() + '\"');
command.append(" channels 1");
command.append(" gain -h");
command.append(" rate 16000");
command.append(" trim");
command.append(" " + startTime.toString());
command.append(" " + '=' + endTime.toString());
Process soxProcess = new ProcessBuilder(command.toString())
.start();
I also tried the same thing, but using an ArrayList.
Found the answer myself, with lots of help from bramp's comment. The problem is easily resolved by first using a List of Strings, and then by separating the non-dash prefixed arguments that require spaces, like sox's effects.
So from something like:
StringBuilder s = new StringBuilder("sox/sox"); // command itself is 'sox'
// everything after this is an argument
s.add(srcFile.getPath());
s.add("-b 16");
s.add(destFile.getPath());
s.add("rate 16000");
s.add("channels 1");
you get:
ArrayList<String> s = new ArrayList<String>();
s.add("sox/sox"); // command/process
// everything after this is an argument
s.add(srcFile.getPath());
s.add("-b 16");
s.add(destFile.getPath());
s.add("rate"); // notice how I had to split up the rate argument
s.add("16000");
s.add("channels"); // same applies here
s.add("1");
I think it may have something to do with how Java sends the arguments, or how SoX receives arguments. I was able to replicate my problem in the terminal by using the following command:
sox/sox test/test.wav -b 16 test/newtest.wav "rate 16000" "channels 1"

Categories

Resources