ProcessBuilder 和 Runtime.exec() 之间的区别
我正在尝试从 java 代码执行外部命令,但我注意到 Runtime.getRuntime().exec(...)
和 new ProcessBuilder(.. .).start()
。
使用Runtime
时:
Process p = Runtime.getRuntime().exec(installation_path +
uninstall_path +
uninstall_command +
uninstall_arguments);
p.waitFor();
exitValue 为 0,命令正常终止。
但是,对于 ProcessBuilder:
Process p = (new ProcessBuilder(installation_path +
uninstall_path +
uninstall_command,
uninstall_arguments)).start();
p.waitFor();
退出值为 1001,并且命令在中间终止,尽管 waitFor
返回。
我应该如何解决 ProcessBuilder
的问题?
I'm trying to execute an external command from java code, but there's a difference I've noticed between Runtime.getRuntime().exec(...)
and new ProcessBuilder(...).start()
.
When using Runtime
:
Process p = Runtime.getRuntime().exec(installation_path +
uninstall_path +
uninstall_command +
uninstall_arguments);
p.waitFor();
the exitValue is 0 and the command is terminated ok.
However, with ProcessBuilder
:
Process p = (new ProcessBuilder(installation_path +
uninstall_path +
uninstall_command,
uninstall_arguments)).start();
p.waitFor();
the exit value is 1001 and the command terminates in the middle, although waitFor
returns.
What should I do to fix the problem with ProcessBuilder
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Runtime.getRuntime().exec(...)
的各种重载采用字符串数组或单个字符串。exec()
的单字符串重载会将字符串标记为参数数组,然后将字符串数组传递给采用字符串的exec()
重载之一大批。另一方面,ProcessBuilder 构造函数仅采用字符串的 varargs 数组或字符串的 List,其中数组或列表中的每个字符串都被假定为单独的字符串。争论。无论哪种方式,获得的参数都会被连接成一个字符串,传递给操作系统来执行。因此,例如,在 Windows 上,
将使用两个给定参数运行
DoStuff.exe
程序。在这种情况下,命令行会被标记化并重新组合在一起。但是,除非
C:\
中恰好有一个名称为DoStuff.exe -arg1 -arg2
的程序,否则将会失败。这是因为没有标记化:假设要运行的命令已经被标记化。相反,您应该使用或替代
The various overloads of
Runtime.getRuntime().exec(...)
take either an array of strings or a single string. The single-string overloads ofexec()
will tokenise the string into an array of arguments, before passing the string array onto one of theexec()
overloads that takes a string array. TheProcessBuilder
constructors, on the other hand, only take a varargs array of strings or aList
of strings, where each string in the array or list is assumed to be an individual argument. Either way, the arguments obtained are then joined up into a string that is passed to the OS to execute.So, for example, on Windows,
will run a
DoStuff.exe
program with the two given arguments. In this case, the command-line gets tokenised and put back together. However,will fail, unless there happens to be a program whose name is
DoStuff.exe -arg1 -arg2
inC:\
. This is because there's no tokenisation: the command to run is assumed to have already been tokenised. Instead, you should useor alternatively
ProcessBuilder.start()
和Runtime.exec()
之间没有区别,因为Runtime.exec()
的实现是:所以代码:
应该是一样的:
感谢dave_thompson_085的评论
There are no difference between
ProcessBuilder.start()
andRuntime.exec()
because implementation ofRuntime.exec()
is:So code:
should be the same as:
Thanks dave_thompson_085 for comment
查看 Runtime.getRuntime().exec() 如何将 String 命令传递给 ProcessBuilder。它使用标记器并将命令分解为单独的标记,然后调用 exec(String[] cmdarray, ......) 构造一个
ProcessBuilder
。如果您使用字符串数组而不是单个字符串来构造 ProcessBuilder,您将得到相同的结果。
ProcessBuilder 构造函数采用 String... 可变参数,因此将整个命令作为单个字符串传递与在终端中用引号调用该命令具有相同的效果:
Look at how
Runtime.getRuntime().exec()
passes the String command to theProcessBuilder
. It uses a tokenizer and explodes the command into individual tokens, then invokesexec(String[] cmdarray, ......)
which constructs aProcessBuilder
.If you construct the
ProcessBuilder
with an array of strings instead of a single one, you'll get to the same result.The
ProcessBuilder
constructor takes aString...
vararg, so passing the whole command as a single String has the same effect as invoking that command in quotes in a terminal:是的,有区别。
Runtime.exec(String)
方法 接受单个命令字符串,并将其拆分为命令和参数序列。ProcessBuilder
构造函数 采用 (varargs) 字符串数组。第一个字符串是命令名称,其余字符串是参数。 (有一个替代构造函数接受字符串列表,但没有一个接受由命令和参数组成的单个字符串。)因此,您告诉 ProcessBuilder 要做的是执行名称包含空格和其他垃圾的“命令”在其中。当然,操作系统找不到该名称的命令,命令执行失败。
Yes there is a difference.
The
Runtime.exec(String)
method takes a single command string that it splits into a command and a sequence of arguments.The
ProcessBuilder
constructor takes a (varargs) array of strings. The first string is the command name and the rest of them are the arguments. (There is an alternative constructor that takes a list of strings, but none that takes a single string consisting of the command and arguments.)So what you are telling ProcessBuilder to do is to execute a "command" whose name has spaces and other junk in it. Of course, the operating system can't find a command with that name, and the command execution fails.