[英]ProcessBuilder - No such file or directory (but Runtime.exec() works)
[英]Java, Runtime.exec or ProcessBuilder: how to know if the file is shell or binary?
我正在寻找一种最有效的方法来决定:
众所周知,要从Java启动shell脚本,应该启动shell:
ProcessBuilder pb = new ProcessBuilder("/bin/sh", "script.sh", "arg1", "arg2);
要启动二进制文件,应该启动二进制文件:
ProcessBuilder pb = new ProcessBuilder("/path/binary", "arg1", "arg2);
如果使用shell执行二进制文件,则会产生错误:
ProcessBuilder pb = new ProcessBuilder("/bin/sh", "/path/binary", "arg1", "arg2);
(sh: cannot execute binary file)
如果在没有shell二进制文件的情况下执行shell脚本,则会产生错误:
ProcessBuilder pb = new ProcessBuilder("script.sh", "arg1", "arg2);
(error 2: file not found)
我的情况是我的应用程序不知道它的启动,二进制或脚本。
启动的应用程序是最终用户提供的事件处理程序。 它很可能是在Unix下执行的shell脚本; 但它可以是Windows下的* .cmd,或者是在一些不起眼的平台下执行的Perl脚本。 毕竟它是Java。
我的第一个天真的尝试是用shell启动命令行,看它是否有效。 如果没有,请尝试将其作为二进制文件执行。
这是丑陋和冒险的:在平台和shell的一些未知组合下,第二次运行仍然可能仍然执行脚本,第二次,具有不可预测的结果。
此外,我无法判断脚本何时启动正常并且由于某些问题而失败,因为我无法启动它。
我现在考虑的最好的事情是:
如果您有任何更好的想法,请告知。
更新/部分解决方案
感谢所有与我分享他们想法的人。
事实证明,我把自己和互联网的其他部分弄糊涂了:)
在用户输入的命令行之前不需要在应用二进制文件前加前缀,前提是:
当我测试我的代码时,这些条件中的一个或另一个没有达到。 :-(
从临时脚本执行测试后,脚本已经执行完毕。
第3点只能由用户完成,并且必须在用户手册中记录。
由于这些脚本传播到目标系统的方式,它们可能不可执行,可能不在PATH中。
我关心的唯一路径是相对路径,因此将./添加到任何相对路径就足够了。
使脚本在Unix(以及任何其他平台)下可执行是一个更大的挑战。 这不是WORA。 在它前面放置/ bin / sh可能会有所帮助,但如果我记得在Solaris下,shell将不会执行非可执行脚本。
我将在本周晚些时候发布另一个更新。
它应该是一个红旗,你必须跳过这些箍只是为了运行一个命令。 首先是因为这变得非常复杂,其次是因为Java被设计为独立于平台。 当您研究特定于操作系统的黑客攻击以使内置类工作时,您应该退后一步并重新检查您的假设。
ProcessBuilder pb = new ProcessBuilder("script.sh", "arg1", "arg2);
(error 2: file not found)
请注意,错误消息是“找不到文件”,而不是“无法执行shell脚本”或某些此类错误。 导致此错误的最可能原因不是您正在执行脚本,而是找不到该脚本。
如果脚本在当前目录中,则需要在前面添加./
。 如果未将可执行文件放在显式路径中,则可执行文件必须位于$PATH
环境变量的其中一个目录中。 当前目录.
默认情况下通常不包含在$PATH
。
ProcessBuilder pb = new ProcessBuilder("./script.sh", "arg1", "arg2);
如果脚本名称是用户提供的值,那么我会对用户征收此要求 - 您可以为它们添加./
,但UNIX程序通常会尽量避免过于有用。 如果他们忘了把./
那就是他们的问题!
一种可能的解决方案是生成一个脚本,该脚本包含程序中的执行脚本/二进制文件。 这样你知道它总是一个脚本。 生成的脚本只执行内部脚本/二进制文件并返回错误代码(并可能重定向输入/输出)。 完成后,您只需删除它即可。 Java允许您非常轻松地创建临时文件。
上
ProcessBuilder pb = new ProcessBuilder(“/ bin / sh”,“/ path / binary”,“arg1”,“arg2);(sh:无法执行二进制文件)
ProcessBuilder pb = new ProcessBuilder(“/ bin / sh”,“ - c”,“/ path / binary”,“arg1”,“arg2);(sh:无法执行二进制文件)
一种选择是接受来自用户的解释器路径作为另一个参数(可能来自已知值的列表)。
(这可能是一个评论。我无法正确格式化)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.