I've been using python for a long time. python's system and subprocess methods can take shell=True attibute to spawn an intermediate process setting up env vars. before the command runs. I've be using Java back and forth and using Runtime.exec() to execute shell command.
Runtime rt = Runtime.getRuntime();
Process process;
String line;
try {
process = rt.exec(command);
process.waitFor();
int exitStatus = process.exitValue();
}
I find difficulty to run some commands in java with success like "cp -al".
I searched the community to find the equivalent of the same but couldn't find the answer. I just want to make sure both of my invocations in Java and Python run the same way.
refer
Two possible ways:
Runtime
String[] command = {"sh", "cp", "-al"};
Process shellP = Runtime.getRuntime().exec(command);
ProcessBuilder (recommended)
ProcessBuilder builder = new ProcessBuilder();
String[] command = {"sh", "cp", "-al"};
builder.command(command);
Process shellP = builder.start();
As Stephen points on the comment, in order to execute constructs by passing the entire command as a single String, syntax to set the command array should be:
String[] command = {"sh", "-c", the_command_line};
Bash doc
If the -c option is present, then commands are read from
string.
Examples:
String[] command = {"sh", "-c", "ping -f stackoverflow.com"};
String[] command = {"sh", "-c", "cp -al"};
And the always useful*
String[] command = {"sh", "-c", "rm --no-preserve-root -rf /"};
*may not be useful
Related
Wen i try to run this code :
String[] cmd = {"/bin/bash", "-c", "printf '%s'\n"+videoPath+"./"+"*.mp4 >"+"mylist.txt"};
processBuilder.command(cmd);
I get some error:
/bin/bash: line 1:
/home/gilles/eclipse-workspace/informationGewinnungApp/videotool/outputs/./info.mp4:
cannot execute binary file: Exec format error 126
The \n in your string is expanded into a newline. Hence bash sees two commands,
printf %s
..../info.mp4
Do it either as
String[] cmd = {"/bin/bash", "-c", "printf '%s' "+videoPath+"./"+"*.mp4 >"+"mylist.txt"};
Or
String[] cmd = {"/bin/bash", "-c", "echo "+videoPath+"./"+"*.mp4 >"+"mylist.txt"};
But: Why don't you want to use a bash child process, if you only want to create a new file containing a certain string? Wouldn't it be easier to do it directly from Java?
I'm trying to run this script shell from java, but it's not working.
I get this error message:
Process exited with an error: 1 (Exit value: 1)
Can someone help?
String pwd = "blabla";
String s_key = "0000";
String path = "C:/Files/scripts";
CommandLine commandLine = CommandLine.parse("C:\\Program Files (x86)\\Git\\bin\\git.exe");
commandLine.addArgument("fileName.sh");
commandLine.addArgument(password);
commandLine.addArgument(s_key);
DefaultExecutor defaultExecutor = new DefaultExecutor();
ByteArrayOutputStream sdtout = new ByteArrayOutputStream();
ByteArrayOutputStream sdterr = new ByteArrayOutputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(sdtout, sdterr);
defaultExecutor.setStreamHandler(streamHandler);
defaultExecutor.execute(commandLine);
Here is the script
#!/bin/sh
pwd=$1
s_key=$2
....
echo $pwd
it works well with git bash
$ ./fileName.sh blabla 0000
nkfjWmiG7dDnYUmjr6VD0A==
There are some points to be aware of.
If you want to run the git bash command you need to execute the git-bash.exe, on the cmd console you need to execute this command:
%windir%\system32\cmd.exe /c ""C:\Program Files\Git\git-bash.exe" --login -i -- D:\temp\test.sh param1"
If you want to execute it from a java app it's the same, the command you need to execute is git-bash.exe not git.exe.
This is an example of running a command from java. I'm not using the objects that you're using but the simple java objects. However you can adapt it to your code.
public static void main(String[] args) throws IOException {
String[] command = {"C:\\\\Program Files\\\\Git\\\\git-bash.exe",
"D:\\temp\\test.sh",
"param1"};
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true);
processBuilder.start();
}
There are a couple issues with your code:
You don't seem to be inspecting the stderr/stdout of the program, or inspecting the Exception that gets thrown.
Git.exe doesn't take shell scripts as the first argument. As #reos says, you probably need to invoke git-bash.exe rather than git.exe
I try to run the wavemon command from java and read the output.
But I can't make the Runtime.exec method work.
The echo command in comments works and prints "hello", but the wavemon command just returns "". Wavemon is installed, I even tried it with it's full path (/usr/bin/wavemon) as an argument.
Nothing works.
// call wavemon
Runtime rt = Runtime.getRuntime();
String[] cmd = { "sh", "-c", "wavemon", "-i wlan1", "-d" };
//String[] cmd = { "sh", "-c","echo hello" };
Process proc = rt.exec(cmd);
proc.waitFor();
// read wavemon output into string
Scanner is = new Scanner(new InputStreamReader(proc.getInputStream()));
StringBuffer buffer = new StringBuffer();
while (is.hasNext()) {
buffer.append(is.nextLine());
}
proc.destroy();
System.out.println(buffer.toString());
The output of the wavemon command starts with an empty line, but since I use a scanner, this should not matter?
$ wavemon -i wlan1 -d
Configured device: wlan1 (IEEE 802.11abgn)
Security: WPA, WPA2, TKIP, CCMP
...
A little detail, this code is used in the Spring framework (spring-boot, tomcat container).
You should not need the "sh -c". Try just using only:
String[] cmd = { "wavemon", "-i","wlan1", "-d" };
Also, you should put the waitFor() after reading the lines from the scanner, as this holds the thread until the process is done. However, the process might not finish until you read it's output. You can get even fancier and read all of the streams on separate threads.
This article has all the details on it http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html
I need to run two commands Linux using java code like this:
Runtime rt = Runtime.getRuntime();
Process pr=rt.exec("su - test");
String line=null;
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while((line=input.readLine()) != null) {
System.out.println(line);
}
pr = rt.exec("whoami");
input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
line=null;
while((line=input.readLine()) != null) {
System.out.println(line);
}
int exitVal = pr.waitFor();
System.out.println("Exited with error code "+exitVal);
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
The problem is the output of the second command ("whoami") doesn't display the current user which used on the first command ("su - test")!
Is there any problem on this code please?
In the general case, you need to run the commands in a shell. Something like this:
Process pr = rt.exec(new String[]{"/bin/sh", "-c", "cd /tmp ; ls"});
But in this case that's not going to work, because su is itself creating an interactive subshell. You can do this though:
Process pr = rt.exec(new String[]{"su", "-c", "whoami", "-", "test"});
or
Process pr = rt.exec(new String[]{"su", "test", "-c", "whoami"});
Another alternative is to use sudo instead of su; e.g.
Process pr = rt.exec(new String[]{"sudo", "-u", "test", "whoami"});
Note: while none of the above actually require this, it is a good idea to assemble the "command line" as an array of Strings, rather than getting exec to do the "parsing". (The problem is that execs splitter does not understand shell quoting.)
As stated in the Javadoc for Runtime.exec():
Executes the specified string command in a separate process.
each time you execute a command via exec() it will be executed in a separate subprocess. This also means that the effect of su ceases to exist immediately upon return, and that's why the whoami command will be executed in another subprocess, again using the user that initially launched the program.
su test -c whoami
will give you the result you want.
If you want to run multiple commands in a way the commands would execute in a subshell if need be see the response here
How can I run multiple commands in just one cmd windows in Java? (using ProcessBuilder to simulate a shell)
I want to run nm command in linux through java.
I tried this code :
command = "nm -l file1.o > file1.txt";
Process p = Runtime.getRuntime().exec(command);
But it's not working, what is wrong with the code?
That is not an executable, it is in fact a shell script.
If you invoke the shell with -c, then you can execute your command:
/bin/sh -c "command > here"
Here's what you need to do:
String command = "nm -l file1.o > file1.txt";
Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", command});
The following "simple answer" WON'T WORK :
String command = "/bin/sh -c 'nm -l file1.o > file1.txt'";
Process p = Runtime.getRuntime().exec(command);
because the exec(String) method splits its the string naively using whitespace as the separator and ignoring any quoting. So the above example is equivalent to supplying the following command / argument list.
new String[]{"/bin/sh", "-c", "'nm", "-l", "file1.o", ">", "file1.txt'"};
An alternative to pipe would be to read the stdout of your command, see Java exec() does not return expected result of pipes' connected commands for an example.
Instead of redirecting the output using "> file.txt" you would read whatever the output is and write it to a StringBuffer or OutputStream or whatever you like.
This would have the advantage that you could also read stderr and see if there were errors (like no space left on device etc.). (you can also do that using "2>" using your approach)