I'm trying to execute in java this command, and I need to get the output
in a java String. The command encrypt plain text with a password phrase and return the plain text encrypted.
The command is:
/bin/sh -c echo "textToEncrypt" | /usr/bin/openssl enc -aes-256-cbc -e -base64 -A -pass pass:passwordPhrase
Screenshot:
I do the following:
I can run the command in the linux shell , and I get an encrypted output string in the shell, like: "U2FsdGVkX1/1UcPzhX7IGgvXdx9YrS+cizrla8UYhU8=", so the command works.
I can run the same command in java 1.7, like the example code below (cryptData method). It runs fine, but I dont get an output (the encrypted data).
I can run any command without "echo" from java, for example, ("ls -fla | more"). Run fine again and I always get the output.
This is the code:
public void cryptData() {
String passwordPhrase="a1b2c3d4e5";
ProcessBuilder processBuilder = new ProcessBuilder();
List<String> commands = new ArrayList<String>();
commands.add("/bin/sh");
commands.add("-c");
commands.add("echo");
commands.add("/"textToCrypt/"");
commands.add("|");
commands.add("/usr/bin/openssl");
commands.add("-aes-256-cbc");
commands.add("-e");
commands.add("-base64");
commands.add("-A");
commands.add("-pass");
commands.add("pass:"+passwordPhrase);
// Run the shell command
processBuilder.command(commands);
try { //standard stringBuilder process
Process process = processBuilder.start();
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println("Output1"+ output);
System.out.println("Output2"+ output.toString());
System.exit(0);
} else {
System.out.println("Error");
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The final result is always: "Success!" but the output is empty or null with this code. What am I doing wrong?
sh -c expects the command to be executed as a single argument. So after adding /bin/sh and -c, you should add the rest of the command as a single argument, like this:
commands.add("/bin/sh");
commands.add("-c");
commands.add("echo /" + textToCrypt + "/ | /usr/bin/openssl -aes-256-cbc " +
"-e -base64 -A -pass pass: " + passwordPhrase);
Related
I am trying to use runtime.getruntime.exec in a Java application.
For quite a while, I've been trying to run different command and I keep getting Error Code 2 which I've found to mean that the file or directory doesn't exist. To test, I attempted to pass a basic command and am getting Error Code 1. Why am I getting this and what does Error Code 1 mean?
Here is my code:
private String executeCommand(String command) {
logger.info("executing command : " + command);
String result = null;
try {
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(command);
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
String line = null;
while ((line = input.readLine()) != null) {
result = result + line;
}
while ((line = stdError.readLine()) != null) {
result = result + line;
}
int exitVal = pr.waitFor();
System.out.println("Exited with error code " + exitVal);
} catch (IOException e) {
e.printStackTrace();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Throwable e) {
e.printStackTrace();
}
logger.info("This is the result:" + result);
return result;
Here is how I call it:
String temp = executeCommand("cd $HOME/my-directory/my-subdirectory");
Here is my output:
INFO : programname - executing command : cd $HOME/my-directory/my-
subdirectory
Exited with error code 1
INFO : programname - This is the result:null/usr/bin/cd[8]: $HOME/my-
directory/my-subdirectory: not found
Runtime.getRuntime().exec(command) is expecting an exe file as its first parameter in the passed string. Commands like (cd, echo, etc...) are specific for the Command Line Tool and will not work as directly passed commands. You will need to invoke the command line tool first and then pass your command as it's arguments:
// Invoke Command Line Tool (.exe is optional) (cmd for windows sh for Linux)
// 1st argument indicates you want to run a command (/C for windows -c for Linux)
// 2nd argument is the cmd line command to run (echo)
Runtime.getRuntime().exec("cmd.exe /C echo helloworld");
Runtime.getRuntime().exec("sh -c echo helloworld");
On a separate note. you will want to initialize your result to be an empty string instead of null. Otherwise the word "null" will be prepended to what your printing out.
Do Process pr = rt.exec("cmd /c "+command);
I am executing grep command from java on a linux file. Its always returning null for the following code.
Process p;
String matchStr="testmatch";
String output = null;
try {
String command = "grep \""+matchStr+"\" "+ filename;
System.out.println("Running command: " + command);
p = Runtime.getRuntime().exec(command);
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while (br.readLine() != null) {
System.out.println("in while loop");
System.out.println("in while loop");
System.out.println("in while loop");
System.out.println(output);
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
// Process your output here
}
System.out.println("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
If i grep it directly it shows output but from java it never gets into while loop.
Please suggest whats wrong here.
The problem is that you do not write anything to output so it stays null. I guess you have to rewrite your while loop like this
while ((output = br.readLine()) != null) {
// Process your output here
}
Take a note that this syntax is discouraged by most style check due to it's abmiguity
Also it's a good idea to place p.waitFor() after while loop so grep would not hang on flushig std(err|out).
UPDATE
Also it is a good idea to use ProcessBuilder (available since java-7) instead of Runtime.getRuntime().exec(...) because you will have more control over the process i.e
final ProcessBuilder builder = new ProcessBuilder();
builder.command("grep", matchStr, filename);
// redirect stderr to stdout
builder.redirectErrorStream(true);
final Process process = builder.start();
BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String output = null;
while ((output = br.readLine()) != null) {
System.out.println(output);
// Process your output here
}
process.waitFor();
After turning your code into a https://stackoverflow.com/help/mcve it works for me.
Here the file does not exist:
robert#habanero:~$ rm /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
exit: 2
Now the file does exist but does not contain the text to be found:
robert#habanero:~$ echo not found > /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
exit: 1
Now the file exists and contains the text:
robert#habanero:~$ echo test this > /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
test this
exit: 0
Here is the code:
import java.io.*;
public class GrepTest {
public static void main(String[] args) throws Exception {
String command = "grep test /home/robert/greptest.txt";
System.out.println("Running command: " + command);
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String output;
while ((output = br.readLine()) != null) {
System.out.println(output);
}
System.out.println("exit: " + p.exitValue());
p.destroy();
}
}
I was recently struggling with a similar issue, and I believe I the solution I found is an answer also to your problem (though your question is a bit malformed as others have pointed out).
The issue pertrains to the quote marks around your search string,
\""+matchStr+"\"
The java exec command will literally deliver these to the grep command, and instead of searching for matchStr, grep will be looking for "matchStr", and the results will not be what you are expecting.
This applies also in case one is executing the command as an array like
final Process process = Runtime.getRuntime().exec(new String[] { "grep", "-C1000", searchString, fileName } );
Pass the plain searchString without including quotation marks into the string.
I am trying to run this command from java code and expecting a file to be generated with 1 liner code :
cut -d , -f 2 /online/data/test/output/2Zip/brita_ids-*.csv | sort -u | tr -d '\n' | sha512sum > /online/data/test/output/file_name.txt
This cmd is fine when I am running from cmd line but something wrong with my java code that I gatting hard time to figure out and I am not seeing the expected file being generated. Any clue whay may have happened here?
Here is my code to generate that file :
public String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
LOG.info( "Executing cmd : " + command );
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null)
{
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
LOG.error( "Error in executing cmd : " + command + " \nError : " + e.getMessage() );
}
return output.toString();
}
Thanks in advance.
As RealSkeptic pointed out, pipe characters (|) are not command arguments; they're interpreted by a shell. And you are calling a command (cut) directly rather than using a shell.
This isn't a direct answer to your question, but you can accomplish your task without any shell commands:
Charset charset = Charset.defaultCharset();
MessageDigest digest = MessageDigest.getInstance("SHA-512");
try (DirectoryStream<Path> dir = Files.newDirectoryStream(
Paths.get("/online/data/test/output/2Zip"), "brita_ids-*.csv")) {
for (Path file : dir) {
Files.lines(file, charset)
.map(line -> line.split(",")[1])
.sorted(Collator.getInstance()).distinct()
.forEach(value -> digest.update(value.getBytes(charset)));
}
}
byte[] sum = digest.digest();
String outputFile = "/online/data/test/output/file_name.txt";
try (Formatter outputFormatter = new Formatter(outputFile)) {
for (byte sumByte : sum) {
outputFormatter.format("%02x", sumByte);
}
outputFormatter.format(" *%s%n", outputFile);
}
Thank you all, specifically #RealSkeptic and #qingl97. With your suggestion, I made a small change and that worked.
Process p = Runtime.getRuntime().exec(
new String[]{"sh","-c",command});
p.waitFor()
Try this if you want to get the output as well. ProcessBuilder would be better for multiple arguments and commans
try {
Process process = Runtime
.getRuntime()
.exec("cut -d , -f 2 /online/data/test/output/2Zip/brita_ids-*.csv | sort -u | tr -d '\n' | sha512sum > /online/data/test/output/file_name.txt");
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line = reader.readLine();
while (line != null) {
// print the output to Console
System.out.println(line);
line = reader.readLine();
}
} catch (Exception e1) {
e1.printStackTrace();
}
System.out.println("Finished");
Something like this if you want a series of commands
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe", "/c", "cd \"C:\\Program Files\\Microsoft SQL Server\" && dir");
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while (true) {
line = r.readLine();
if (line == null) { break; }
System.out.println(line);
}
From SOQuestion
public class RunBashCommand {
public synchronized boolean RunInBash(String command) {
System.out.println("CMD: "+command);
/*String s; not working this code also
Process p;
try {
Process p = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((s = br.readLine()) != null)
System.out.println("line: " + s);
p.waitFor();
System.out.println ("exit: " + p.exitValue());
PrintBufferReader(getError(p));
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}*/
try {
Process p = new ProcessBuilder("/bin/sh", command).start();
/*Process p = new ProcessBuilder("/bin/bash", command).start();*/
PrintBufferReader(getError(p));
/*p.destroy();*/
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
private static BufferedReader getOutput(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
private static BufferedReader getError(Process p) {
return new BufferedReader(new InputStreamReader(p.getErrorStream()));
}
private void PrintBufferReader(BufferedReader br) throws IOException {
int value = 0;
String s = "";
while((value = br.read()) != -1)
{
char c = (char)value;
s = s+c;
}
System.out.println("EEEE: "+s);
}
}
I tried this code, but it did not work.
following output came:
CMD: cd /home/jeevan/workspace/apb_proj/; source init.csh
EEEE: /bin/sh: cd /home/jeevan/workspace/apb_proj/; source init.csh: No such file or directory
CMD: cd /home/jeevan/workspace/apb_proj/verif/compile/; make clean; make compile; make elab
EEEE: /bin/sh: cd /home/jeevan/workspace/apb_proj/verif/compile/; make clean; make compile; make elab: No such file or directory
CMD: sh /home/jeevan/workspace/apb_proj/verif/test_lib/src/apb_test31/runme.csh
EEEE: /bin/sh: sh /home/jeevan/workspace/apb_proj/verif/test_lib/src/apb_test31/runme.csh: No such file or directory
can some one help?
You're effectively running:
/bin/sh "cd /home/jeevan/workspace/apb_proj/; source init.csh"
When you run /bin/sh this way, it treats its first argument as the name of a file to execute as a shell script. Of course, there's no file named "cd /home/jeevan/workspace/apb_proj/; source init.csh", so you get an error message.
The correct way to invoke sh with a command as an argument is like this:
/bin/sh -c "cd /home/jeevan/workspace/apb_proj/; source init.csh"
Using process builder, you'd do:
Process p = new ProcessBuilder("/bin/sh", "-c", command).start();
The next problem that you're likely to run into is that it appears that the command you're trying to invoke is a csh command, not an sh command. "source" is a csh command, and the file you're trying to source is called "init.csh". So maybe you want to invoke csh instead of sh:
Process p = new ProcessBuilder("/bin/csh", "-c", command).start();
You need to split command arguments into separate parameters: not ProcessBuilder("bin/sh", "cd foo/bar") but ProcessBuilder("bin/sh", "cd", "foo/bar").
You can't use shell metacharacters (like ";") too. To run multiple commands, you have to start multiple processes.
Put all your commands into a List and pass it as the argument to the ProcessBuilder. As an alternative you can start the shell process, get it's OutputStream and write commands into this stream to execute them.
I have this bash:
#!/bin/bash
# File to be tagged
inputfile="/dfs/sina/SinaGolestanirad-Project-OneTextEachTime/SinaGolestanirad-Project/Text.txt"
#inputfile="test/SampleInputs/longParagraph.txt"
# Tagged file to be created
#outputfile="test/SampleOutputs/NERTest.conll.tagged.txt"
outputfile="/dfs/sina/SinaGolestanirad-Project-OneTextEachTime/SinaGolestanirad-Project/1.Generate-Basic-Questions/Tagged-Named-Entites-Text.txt"
# Config file
#configfile="config/conll.config"
configfile="config/ontonotes.config"
# Classpath
cpath="target/classes:target/dependency/*"
CMD="java -classpath ${cpath} -Xmx8g edu.illinois.cs.cogcomp.LbjNer.LbjTagger.NerTagger -annotate ${inputfile} ${outputfile} ${configfile}"
echo "$0: running command '$CMD'..."
$CMD
When I run either java codes below they do not give any errors but they just show the bash file in my Eclipse Console, in other words they do not run the bash !! and the value for process.exitValue() is 1, by the way, my OS is CentOS, linux.
Firs JAVA code :
try {
Process process = new ProcessBuilder(command).start();
process.waitFor();
System.out.println(process.exitValue());
BufferedReader buf = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = buf.readLine()) != null) {
System.out.println("exec response: " + line);
}
} catch (Exception e) {
System.out.println(e);
}
Second JAVA code :
String command = "/dfs/sina/SinaGolestanirad-Project-OneTextEachTime/"
+ "SinaGolestanirad-Project/1.Generate-Basic-Questions/1.IllinoisNerExtended-DO-NOT-OPEN-BY-ECLIPSE/plaintextannotate-linux.sh";
StringBuffer output = new StringBuffer();
Process p;
try {
String[] cmd = new String[]{"/bin/bash",command};
p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
System.out.println(output.toString());
} catch (Exception e) {
e.printStackTrace();
}
I also checked the bash file permission and it is executable as a program.
How can I run the bash file? The bash should run another program written in java.
-- LeBarton what is the exit code?
Check the output of p.exitValue()
p.waitFor()
InputStreamReader inputStreamReader = new InputStreamReader(p.getErrorStream());
While (inputStreamReader.ready()) { System.out.println(inputStreamReader.read(); }
This will show you the error output. Add this to the bottom below the try.. catch.
You will see the output that you would see on the command line. It will help you narrow down the error.
I found a link which may help, if your bash read some environmental variables.
$PATH variable isn't inherited through getRuntime().exec