如何在java中运行OSX的sudo命令
我正在使用javafx开发应用程序,我正在尝试使用终端中的命令打开应用程序,我正在使用我的java代码运行该命令我的命令有一些变量它有我的安装程序文件的路径,该路径并不总是相同的,因为随着版本的更新,文件名可能会不同。如何在java中运行OSX的sudo命令,java,bash,macos,Java,Bash,Macos,我正在使用javafx开发应用程序,我正在尝试使用终端中的命令打开应用程序,我正在使用我的java代码运行该命令我的命令有一些变量它有我的安装程序文件的路径,该路径并不总是相同的,因为随着版本的更新,文件名可能会不同。 下面是一个我如何运行命令的示例,它不是我正在运行的确切命令,但命令格式是相同的 Process process = Runtime.getRuntime().exec("echo password | sudo -S open -a safari"); String li
下面是一个我如何运行命令的示例,它不是我正在运行的确切命令,但命令格式是相同的
Process process = Runtime.getRuntime().exec("echo password | sudo -S open -a safari");
String line;
BufferedReader input = new BufferedReader(new InputStreamReader(pb.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
进程没有给出任何输出,它在那里停止,什么也没有发生。
我在终端上试过同样的命令,效果很好
我尝试过在这个链接中提到的东西
但它也不起作用
我还在java代码中运行类似“chmod+x”的命令,这些命令运行良好。
我的原始命令如下所示:-
runCommand = "echo" + " " + password + "| sudo -S " + "\"" + a.getAbsolutePath() + "\"" + " --deploymentFile="
+ "\"" + b.getAbsolutePath() + "\"";
其中a.getAbsolutePath()是安装程序文件的路径,b.getAbsolutePath()是用于安装应用程序的部署文件的路径
pb.getInputStream()
打印命令,当我复制粘贴到终端时,它运行正常
pb.getErrorStream()
什么都不给
我试过跑步
String[] cmd = {"/bin/bash","-c","echo tester| sudo -S ","\"",a.getAbsolutePath(),"\"","\""," --deploymentFile=","\"",b.getAbsolutePath()};
及
也
这里我得到了以下错误
getErrorStreamusage: sudo -h | -K | -k | -L | -V
getErrorStreamusage: sudo -v [-AknS] [-g groupname|#gid] [-p prompt] [-u user name|#uid]
getErrorStreamusage: sudo -l[l] [-AknS] [-g groupname|#gid] [-p prompt] [-U user name] [-u
getErrorStream user name|#uid] [-g groupname|#gid] [command]
getErrorStreamusage: sudo [-AbEHknPS] [-C fd] [-g groupname|#gid] [-p prompt] [-u user
getErrorStream name|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] [<command>]
getErrorStreamusage: sudo -e [-AknS] [-C fd] [-g groupname|#gid] [-p prompt] [-u user
getErrorStream name|#uid] file ...
getErrorStreamusage:sudo-h |-K |-K |-L |-V
getErrorStreamusage:sudo-v[-AknS][g groupname |#gid][p prompt][u user name |#uid]
getErrorStreamusage:sudo-l[l][AknS][g groupname |#gid][p prompt][U用户名][U
getErrorStream用户名|#uid][g组名|#gid][command]
getErrorStreamusage:sudo[-AbEHknPS][C fd][g groupname |#gid][p prompt][u user
getErrorStream名称|#uid][g组名|#gid][VAR=value][i |-s][]
getErrorStreamusage:sudo-e[-AknS][C fd][g groupname |#gid][p prompt][u user
getErrorStream名称|#uid]文件。。。
我认为您必须使用应用程序的完整路径。这应该起作用:
Runtime rt = Runtime.getRuntime();
rt.exec("echo password | sudo -S open -a /Applications/Safari.app");
更新:
根据您的评论,您可以尝试拆分流程。open
需要交互式会话的可能性很大
创建一个脚本(例如openSafari.sh),以用户身份打开Safari
#!/etc/bash
echo $1 | sudo -S open -a /Applications/Safari.app &
使其可执行:chmod+xopensafari.sh
,并从java调用该脚本
Runtime rt = Runtime.getRuntime();
rt.exec("/pathTo/openSafari.sh 'sudoPassword'");
sudo
我强烈建议编辑sudoers文件,允许运行应用程序的用户通过sudo使用特定命令,而无需提示输入密码,而不是执行echo passwd | sudo…
构造
这样可以避免将密码存储在应用程序或配置文件中的clear(或者最好是稍微模糊)中,并且避免使用调用sudo等的shell脚本调用shell
可以通过命令visudo
编辑Sudoers。请参见这里的示例,它是如何在unbuntu上完成的,但在任何unix上都是一样的
附加参考:
我想你问错问题了
mac上的授权
在mac上,需要执行需要额外权限的操作的应用程序不应该使用sudo启动
应用程序应该使用授权服务
参考资料:
String[] cmd = {"/bin/bash","-c","echo password | sudo -S open -a <path to app>"};
Process pb = Runtime.getRuntime().exec(cmd);
String[]cmd={”/bin/bash“,“-c”,“echo password | sudo-S open-a”};
进程pb=Runtime.getRuntime().exec(cmd);
运行时.exec()方法直接运行给定的命令,而不是通过shell。您正在使用的特定重载在空白处标记命令,并将生成的标记解释为命令和参数的名称。您的调用执行的唯一命令
Runtime.getRuntime().exec("echo password | sudo -S open -a safari");
。。。因此是回声;其他一切都是争论。结果是将以下输出转换为流程的标准输出:
密码| sudo-S open-a safari
至少有两种方法可以实现你看起来想要的。对原始代码最简单的修改可能是
Process process = Runtime.getRuntime().exec(
new String[] { "bash", "-c", "echo password | sudo -S open -a safari" });
它通过显式调用shell来运行命令,实现了您认为得到的结果
但这是一个巨大的安全风险,因为密码将以纯文本形式出现在进程列表中。相反,您可以直接在密码中输入Java程序提要,然后避免涉及bash
:
Process process = Runtime.getRuntime().exec("/usr/bin/sudo -S open -a safari");
Writer toSudo = new OutputStreamWriter(process.getOutputStream());
String password = "password";
toSudo.write(password);
toSudo.write('\n'); // sudo's docs demand a newline after the password
toSudo.close(); // but closing the stream might be sufficient
其他考虑:
- 如图所示,为
命令提供完整路径是明智的,以避免运行恰好在路径中首先找到的不同sudo
。由于您将为其提供特权帐户的密码,因此将运行恶意程序的可能性降至最低非常重要sudo
- 避免在程序或配置文件中存储密码也是明智的;因此,涉及向
提供密码的解决方案也应该涉及从用户以交互方式输入密码sudo
- 具有安全意识的Java程序通常更喜欢将密码保存在
数组中,而不是保存在char
s中,以便在不再需要密码时主动清除密码<代码>字符串s无法更改,并且它们可能会无限期地挂在VM内部(甚至比许多其他对象更频繁)String
- 一般来说,您需要同时排出
进程的输入流和错误流,无论您是否对内容执行任何操作。如果不这样做,则外部进程可能会阻塞和/或无法退出。不过,这可能不是safari的问题,因为我认为它通常不会在这些流上产生任何输出
- 也许可以用这个
你可以设置
Process process = Runtime.getRuntime().exec("/usr/bin/sudo -S open -a safari");
Writer toSudo = new OutputStreamWriter(process.getOutputStream());
String password = "password";
toSudo.write(password);
toSudo.write('\n'); // sudo's docs demand a newline after the password
toSudo.close(); // but closing the stream might be sufficient