I have a requirement to run the below command from Java
echo <inputMessage> | iconv -f utf8 -t Cp930
When i use the below code to run the command i see only the echo part is executed but the piping is not happening
public static String callInconverter2(String input,String codePage) throws IOException {
try{
// String command = "echo asdasdasd | iconv -f UTF-8 -t Cp930";
Process p = Runtime.getRuntime().exec("echo "+input+"| iconv -f UTF-8 -t "+codePage);
String s = null;
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
StringBuilder sb = new StringBuilder();
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
sb.append(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
sb.append(s);
}
return sb.toString();
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
return e.getMessage();
}
}}
I am new to Runtime. is there anything am missing.
Tried the method suggested by thomas
String command = "echo asdasdasd | iconv -f UTF-8 -t Cp930";
Process p = Runtime.getRuntime().exec("bash -c \""+command+"\"");
was getting an error asdasdasd: -c: line 0: unexpected EOF while looking for matching `"'asdasdasd: -c: line 1: syntax error: unexpected end of file
is there anything am missing out
Run a shell, with that command -- bash, tcsh, whichever one you normally use.
bash -c "echo | iconv -f utf8 -t Cp930" // or
bash -lc "echo | iconv -f utf8 -t Cp930"
Piping is a shell functionality.
Thus:
Runtime rt = Runtime.getRuntime();
String cmd = "echo | iconv -f utf8 -t Cp930";
rt.exec("bash -c \""+cmd+"\"");
See the bash manual for invocation options. http://www.gnu.org/software/bash/manual/html_node/Invoking-Bash.html#Invoking-Bash
Related
I have a function to execute a system command:
public String cmd(String s) {
String out = "";
try {
Runtime run = Runtime.getRuntime();
Process pr = run.exec(s.split(" "));
pr.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = "";
while ((line=buf.readLine())!=null) {
out+=line+"\n";
}
} catch(Exception e) {
e.printStackTrace();
}
return out;
}
The command passes through:
cmd("nmap -sL -n 192.168.1.0/24 | awk '/Nmap scan report/{print $NF}'");
Expected Output:
192.168.1.0
192.168.1.1
...
Actual Output:
Starting Nmap 7.80 ( https://nmap.org ) at 2021-04-12 20:27 EET
Nmap scan report for 192.168.1.0 ...
Similar questions answers this well:
Using Java ProcessBuilder to Execute a Piped Command
Java program not getting output from terminal
To execute a pipeline, you have to invoke a shell, and then run your commands inside that shell.
Process p = new ProcessBuilder().command("bash", "-c", command).start();
bash invokes a shell to execute your command and -c means commands are read from string. So, you don't have to send the command as an array in ProcessBuilder.
Adapted to you case
String cmd(String command) {
ProcessBuilder builder = new ProcessBuilder();
builder.redirectErrorStream(true); // add stdErr to output
Process process = builder.command("bash", "-c", command).start();
StringBuilder processOutput = new StringBuilder(); // add lines easier
// try-with to auto-close resources
try (BufferedReader processOutputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));) {
String readLine;
while ((readLine = processOutputReader.readLine()) != null) {
processOutput.append(readLine + System.lineSeparator()); // use system's line-break
}
process.waitFor();
}
return processOutput.toString().trim();
}
Then call as expected:
cmd("nmap -sL -n 192.168.1.0/24 | awk '/Nmap scan report/{print $NF}'");
Note: I enhanced it a bit to
use try-with-resources to deal cleanly with resources
add output from StdErr
use a StringBuilder to concatenate output lines
use System.lineSeparator for platform-independency (Win/Mac/Linux/Unix)
Inspired by:
read the output from java exec
The pipe is interpreted by the shell. It executes one command then passes the output of one command into the next one. You could emulate this in Java starting both commands and then pumping the OutputStream of the first program to the InputStream of the second.
Alternatively if you don't want to do this you can still call something like "sh -c 'command1 | command2"
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);
I'm running a shell script command in java program using ProcessBuilder, here is my code :
String lastLine = "";
ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash", "-c", "echo $(ps -eo pid,args | grep -v grep | grep -v \"$$"\ | grep feature_service.sh | awk '{print $1}')");
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
lastLine = line;
}
Output from this : empty string ("")
But if i run the same command on terminal it is working fine (pid of process).
Please help me.
Following simplified Shell command is working.
ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash",
"-c",
"ps -eo pid,args|grep [f]eature_service.sh|awk '{print $1}'|tr '\\n' ' '");
ps -eo pid,args - list the process ID and the arguments
grep [f]eature_service.sh - grep for the string feature_service.sh in the arguments, the [f] avoid the multiple usage of grep in the chain
awk '{print $1}' - print the first column of the output, using default whitespace characters as delimiter
tr '\n' ' ' - replace all newline cracaters in the output by a space character
I can use Runtime.exec() to execute shell commands like "getprop" and "ls system" and they work fine.
However, when I use "echo $BOOTCLASSPATH", "echo \\$BOOTCLASSPATH" or "echo HelloWorld", it won't show it in stdout.
The logcat shows:
I/AndroidRuntime( 4453): VM exiting with result code -1.
Here's my code:
try {
java.lang.Process proc = Runtime.getRuntime().exec("echo -e \\$BOOTCLASSPATH");
String line = null;
InputStream stderr = proc.getErrorStream();
InputStreamReader esr = new InputStreamReader (stderr);
BufferedReader ebr = new BufferedReader (esr);
while ( (line = ebr.readLine()) != null )
Log.e("FXN-BOOTCLASSPATH", line);
InputStream stdout = proc.getInputStream();
InputStreamReader osr = new InputStreamReader (stdout);
BufferedReader obr = new BufferedReader (osr);
while ( (line = obr.readLine()) != null )
Log.i("FXN-BOOTCLASSPATH", line);
int exitVal = proc.waitFor();
Log.d("FXN-BOOTCLASSPATH", "getprop exitValue: " + exitVal);
} catch (Exception e) {
e.printStackTrace();
}
#Adi Tiwari, I've found the cause.
Runtime.getRuntime.exec() doesn't execute a shell command directly, it executes an executable with arguments.
"echo" is a builtin shell command. It is actually a part of the argument of the executable sh with the option -c.
Commands like ls are actual executables.
You can use type echo and type ls command in adb shell to see the difference.
So final code is:
String[] cmdline = { "sh", "-c", "echo $BOOTCLASSPATH" };
Runtime.getRuntime().exec(cmdline);
I'm executing some commands from the command line in my java program, and it appears that it doesn't allow me to use "grep"? I've tested this by removing the "grep" portion and the command runs just fine!
My code that DOESN'T work:
String serviceL = "someService";
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("chkconfig --list | grep " + serviceL);
Code that does work:
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("chkconfig --list");
Why is this? And is there some sort of correct method or workaround? I'm aware that I could just parse the entire output, but I would find it easier to do it all from the command line. Thanks.
The pipe (like redirection, or >) is a function of the shell, and so executing it directly from Java won't work. You need to do something like:
/bin/sh -c "your | piped | commands | here"
which executes a shell process within the command line (including pipes) specified after the -c (in quotes).
So, here's is a sample code that works on my Linux OS.
public static void main(String[] args) throws IOException {
Runtime rt = Runtime.getRuntime();
String[] cmd = { "/bin/sh", "-c", "ps aux | grep skype" };
Process proc = rt.exec(cmd);
BufferedReader is = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while ((line = is.readLine()) != null) {
System.out.println(line);
}
}
Here, I'm extracting all my 'Skype' processes and print the content of the process input stream.
You're trying to use piping which is a function of the shell ... and you're not using a shell; you're exec'ing the chkconfig process directly.
The easy solution would be to exec the shell and have it do everything:
Process proc = rt.exec("/bin/sh -c chkconfig --list | grep " + serviceL);
That being said ... why are you piping to grep? Just read the output of chkconfig and do the matching yourself in java.
String[] commands = { "bash", "-c", "chkconfig --list | grep " + serviceL };
Process p = Runtime.getRuntime().exec(commands);
or if you are in a linux env just use grep4j