Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在java中运行OSX的sudo命令_Java_Bash_Macos - Fatal编程技术网

如何在java中运行OSX的sudo命令

如何在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

我正在使用javafx开发应用程序,我正在尝试使用终端中的命令打开应用程序,我正在使用我的java代码运行该命令我的命令有一些变量它有我的安装程序文件的路径,该路径并不总是相同的,因为随着版本的更新,文件名可能会不同。
下面是一个我如何运行命令的示例,它不是我正在运行的确切命令,但命令格式是相同的

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
    数组中,而不是保存在
    String
    s中,以便在不再需要密码时主动清除密码<代码>字符串s无法更改,并且它们可能会无限期地挂在VM内部(甚至比许多其他对象更频繁)

  • 一般来说,您需要同时排出
    进程的输入流和错误流,无论您是否对内容执行任何操作。如果不这样做,则外部进程可能会阻塞和/或无法退出。不过,这可能不是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