I need to run a shell command in Windows:
c:\Python27\python.exe c:\probabilistic_cracker\process.py dic2.txt
which is running fine in a command shell.
In Java I do this:
ProcessBuilder pb = new ProcessBuilder(Arrays.asList("c:\\Python27\\python", " c:\\probabilistic_cracker\\process.py"," dic2.txt"));
Process p = pb.start();
or this
ProcessBuilder pb = new ProcessBuilder("c:\\Python27\\python", " c:\\probabilistic_cracker\\process.py"," dic2.txt");
in both cases the result is
c:\Python27\python: can't open file ' c:\probabilistic_cracker\process.py': [Errno 22] Invalid argument
Your command is built correctly but the way you pass it to ProcessBuilder isn't, as stated in its documentation you pass the args directly the way they are, there's no need to add spaces since the ProcessBuilder will take care of that for you.
ProcessBuilder pb = new ProcessBuilder("c:\\Python27\\python", "c:\\probabilistic_cracker\\process.py","dic2.txt");
So just removing those whitespaces you have in the beginning of each argument string will do the trick.
Related
I'm trying to use Java's ProcessBuilder class to execute a command that has a pipe in it. For example:
ls -l | grep foo
However, I get an error:
ls: |: no such file or directory
Followed by:
ls: grep: no such file or directory
Even though that command works perfectly from the command line, I can not get ProcessBuilder to execute a command that redirects its output to another.
Is there any way to accomplish this?
This should work:
ProcessBuilder b = new ProcessBuilder("/bin/sh", "-c", "ls -l| grep foo");
To execute a pipeline, you have to invoke a shell, and then run your commands inside that shell.
The simplest way is to invoke the shell with the command line as the parameter. After all, it's the shell which is interpreting "|" to mean "pipe the data between two processes".
Alternatively, you could launch each process separately, and read from the standard output of "ls -l", writing the data to the standard input of "grep" in your example.
Since Java 9, there’s genuine support for piplines in ProcessBuilder.
So you can use
List<String> result;
List<Process> processes = ProcessBuilder.startPipeline(List.of(
new ProcessBuilder("ls", "-l")
.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE),
new ProcessBuilder("grep", "foo")
.redirectError(ProcessBuilder.Redirect.INHERIT)
));
try(Scanner s = new Scanner(processes.get(processes.size() - 1).getInputStream())) {
result = s.useDelimiter("\\R").tokens().toList();
}
to get the matching lines in a list.
Or, for Windows
List<String> result;
List<Process> processes = ProcessBuilder.startPipeline(List.of(
new ProcessBuilder("cmd", "/c", "dir")
.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE),
new ProcessBuilder("find", "\"foo\"")
.redirectError(ProcessBuilder.Redirect.INHERIT)
));
try(Scanner s = new Scanner(processes.get(processes.size() - 1).getInputStream())) {
result = s.useDelimiter("\\R").tokens().toList();
}
These examples redirect stdin of the first process and all error streams to inherit, to use the same as the Java process.
You can also call .redirectOutput(ProcessBuilder.Redirect.INHERIT) on the ProcessBuilder of the last process, to print the results directly to the console (or wherever stdout has been redirected to).
I am currently trying to write a small program in java which should take over the job of an old batch script I've been using.
This batch script executes a program called sum.exe (Supermicro Update Manager).
However, no matter which way I try, the program either does not respond, or straight up tells me it can't find the file in the directory where the file is.
boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
ProcessBuilder builder = new ProcessBuilder("C:\\Users\\[Username]\\SUM\\sum.exe");
if (isWindows) {
builder.command("sum.exe", "-i 192.168.4.10 -u ADMIN -p ADMIN -c CheckOOBSupport");
} else {
builder.command("sh", "-c", "ls");
}
builder.redirectErrorStream(true);
Process process = builder.start();
StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), System.out::println);
StreamGobbler streamGobblerErrors = new StreamGobbler(process.getErrorStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
Executors.newSingleThreadExecutor().submit(streamGobblerErrors);
int exitCode = process.waitFor();
assert exitCode == 0;
This is the code I currently have. The command I'm trying to call here will 100% give an error, so I made sure to redirect those as well.
As far as I understood, there are 3 different ways to set a Filepath for the Processbuilder.
Either you:
Set the path in the constructor
Set the path between your executable and arguments in the .command() method
Or you set the directory of the builder by creating a new file (and using System.Property)
I have a complete copy of the SUM-Folder under: C:\Users\[Username]\SUM, and I have tried all 3 options listed above with this, but always got the error message that the system could not find the file specified
Additionally, I'm still not sure if the command would even work this way. I have only ever used sum.exe via batch-Script or cmd.exe itself, so wouldn't the command need to be
builder.command("cmd.exe", "sum.exe -i 192.168.4.10 -u ADMIN -p ADMIN -c CheckOOBSupport)
instead?
Can anyone tell me what I'm doing wrong?
Thanks!
The ProcessBuilder command line is passed in the constructor or the command() method so in your example you've overridden the value used.
Choose the way you need:
ProcessBuilder builder = new ProcessBuilder("C:\\Users\\[Username]\\SUM\\sum.exe",
"-i", "192.168.4.10",
"-u", "ADMIN","-p", "ADMIN",
"-c", "CheckOOBSupport");
or
ProcessBuilder builder = new ProcessBuilder();
builder.command("sum.exe",
"-i", "192.168.4.10",
"-u", "ADMIN","-p", "ADMIN",
"-c", "CheckOOBSupport");
Note also that the arguments for the command need to supplied as separate string values rather than all concatenated together as one value, and you need absolute path to "sum.exe" if that is not found in the current directory or under a directory of environment variable "Path".
I'm working with the java ProcessBuilder class to start an instance of nmap on my windows workstation.
The following code produces an exception:
java.io.IOException: Cannot run program "C:\Program Files (x86)\Nmap\nmap.exe -T4 -A -v --max-scan-delay 0ms --min-rate 1000000 --max-retries 0 -oX - 192.168.1.1 ": CreateProcess error=2, The system cannot find the file specified
The value of command is:
C:\Program Files (x86)\Nmap\nmap.exe -T4 -A -v --max-scan-delay 0ms --min-rate 1000000 --max-retries 0 -oX - 192.168.1.1
Running the command is generated right in a command window executes properly.
Any ideas?
String command = this.getCommand().toString();
ExecutionResults results = new ExecutionResults();
ProcessBuilder procBuilder = new ProcessBuilder(new String[]{command.toString()});
try {
Process e = procBuilder.start();
results.setErrors(this.convertStream(e.getErrorStream()));
results.setOutput(this.convertStream(e.getInputStream()));
You're passing the whole command (including parameters) as a single parameter of the ProcessBuilder constructor. It takes a String[], where the first item should be the path to the executable, and the other items should be the parameters. Try
command.split(" ")
instead of
new String[]{command.toString()}
Edit: I see that you have spaces in your path, that will break it :( you could try splitting the executable path and the arguments into two strings. And the constructor argument will be a String[] containing the path itself as the first item and then an array of the parameters split by space.
OR: if you don't mind not using the ProcessBuilder.. this is much simpler:
Process e = Runtime.getRuntime().exec(command);
It is simple from the exception itself,
java.io.IOException: Cannot run program "C:\Program Files (x86)\Nmap\nmap.exe -T4 -A -v --max-scan-delay 0ms --min-rate 1000000 --max-retries 0 -oX - 192.168.1.1 ": CreateProcess error=2, The system
Process builder taking the whole line thinking it is as an executable and trying to run that. Just use the below example,
ProcessBuilder procBuilder = new ProcessBuilder(new String[]{"C:\Program Files (x86)\Nmap\nmap.exe"});
procBuilder.start();
This will work fine. So this is not an issue what you think that java is unable to find the executable. It is taking whole line as an executable. Better you do like below,
ProcessBuilder procBuilder = new ProcessBuilder(new String[]{"C:\Program Files (x86)\Nmap\nmap.exe", "-T4", "-A"}); //add all params
procBuilder.start();
Try this, it should work fine
As the other answers have indicated, your immediate problem is that you're passing an entire command line as if it's the name of a program to run. CreateProcess is looking for a program named "C:\Program Files (x86)\Nmap\nmap.exe -T4 -A etc" and failing to find it.
If you have a string containing a command to run (a program name with arguments, redirection, and so on), then the simplest way to run it is to launch it via the command line processor. Here's a simple example of doing that:
public static void main(String[] args) throws IOException, InterruptedException {
String command = "dir /w";
ProcessBuilder procBuilder = new ProcessBuilder(new String[]{"cmd", "/c", command});
procBuilder.redirectInput(Redirect.INHERIT);
procBuilder.redirectOutput(Redirect.INHERIT);
procBuilder.redirectError(Redirect.INHERIT);
Process p = procBuilder.start();
int ecode = p.waitFor();
System.err.println("Exit code " + ecode);
}
It might be because of a couple of reasons from my experience
Firewall would be removed certain files necessary for the installer. So would suggest to uninstall and reinstall
Can also be because of spaces in the folder path, would suggest to install in new folder which does not have spaces in the path.
I am working on a java program, where i need to invoke a bash script that takes a string as an argument. so I've written the code:
Process p = Runtime.getRuntime().exec("./script \"message send\"");
but it seems as if the terminal isn't recognizing the quotes (") as quotes, and referring to the term "message send" as two arguments: "message and send", and so the script is not invoked properly.
anyone have any idea what i can do?
You can perform this by using ProcessBuilder.
ProcessBuilder processBuilder = new ProcessBuilder();
p.command("cmd_to_run", "args_if_any");
p.start();
How can I execute a Java System (shell) command that has a space in the pathname?
I've tried putting quotes and a backslash (), But it does not work.
ln -s "dir1/dir2" "my\ dir/dir2"
By far the most reliable way is to use Runtime.exec(String[] cmdarray).
If you use Runtime.exec(String command), Java only splits the command on whitespace.
the command string is broken into tokens using a StringTokenizer created by the call new StringTokenizer(command) with no further modification of the character categories. The tokens produced by the tokenizer are then placed in the new string array cmdarray, in the same order.
See also g++: File not found
Or use ProcessBuilder something like this:
ProcessBuilder pb = new ProcessBuilder("ln", "-s", "dir1/dir2", "my dir/dir2");
Process p = pb.start();
Do you really need to execute it in a shell (e.g. do you need to shell expansion of things like ~ or *, etc)? If not, you could invoke ln directly:
Process p =
Runtime.getRuntime()
.exec(new String[]{"/bin/ln","-s","dir1/dir2", "my\\ dir/dir2"});
If you really need a shell, try this (this may need a little tweaking depending on how the shell processes the quotes):
Process p =
Runtime.getRuntime()
.exec(new String[]{"/bin/sh", "-c", "ln -s \"dir1/dir2\" \"my\\ dir/dir2\""});
Edit:
I was under the impression the second path has a literal backslash in it. If it's not supposed to remove the \\ from the string literals above.
None of these work on Lion. However, the following does work, and is backwards compatible for Tiger.
Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","/path/to/file/space*init"});
You can use it in the following way without having to introduce any backslashes:
Runtime.getRuntime().exec(new String[]{"ln", "-s", "dir1/dir2", "my dir/dir2"});