27

我正在使用 ProcessBuilder 执行 bash 命令:

import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            Process pb = new ProcessBuilder("gedit").start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

但我想做这样的事情:

Process pb = new ProcessBuilder("sudo", "gedit").start();

如何将超级用户密码传递给bash?

("gksudo", "gedit")不会成功,因为它自 Ubuntu 13.04 以来已被删除,我需要使用默认可用的命令来执行此操作。

编辑

gksudo 在最后一次更新中回到了 Ubuntu 13.04。

4

6 回答 6

40

我认为您可以使用它,但我有点犹豫是否要发布它。所以我只想说:

使用这个需要您自担风险,不推荐,不要起诉我,等等......

public static void main(String[] args) throws IOException {

    String[] cmd = {"/bin/bash","-c","echo password| sudo -S ls"};
    Process pb = Runtime.getRuntime().exec(cmd);

    String line;
    BufferedReader input = new BufferedReader(new InputStreamReader(pb.getInputStream()));
    while ((line = input.readLine()) != null) {
        System.out.println(line);
    }
    input.close();
}
于 2013-09-09T22:51:33.170 回答
14

使用 visudo 编辑 /etc/sudoers 并为您的用户授予特定脚本的 NOPASSWD 权限:

用户名 ALL=(ALL) NOPASSWD: /opt/yourscript.sh

于 2016-09-02T10:31:51.593 回答
9

我的解决方案不会在命令行中公开密码,它只是将密码提供给进程的输出流。这是一个更灵活的解决方案,因为允许您在需要时向用户请求密码。

public static boolean runWithPrivileges() {
    InputStreamReader input;
    OutputStreamWriter output;

    try {
        //Create the process and start it.
        Process pb = new ProcessBuilder(new String[]{"/bin/bash", "-c", "/usr/bin/sudo -S /bin/cat /etc/sudoers 2>&1"}).start();
        output = new OutputStreamWriter(pb.getOutputStream());
        input = new InputStreamReader(pb.getInputStream());

        int bytes, tryies = 0;
        char buffer[] = new char[1024];
        while ((bytes = input.read(buffer, 0, 1024)) != -1) {
            if(bytes == 0)
                continue;
            //Output the data to console, for debug purposes
            String data = String.valueOf(buffer, 0, bytes);
            System.out.println(data);
            // Check for password request
            if (data.contains("[sudo] password")) {
                // Here you can request the password to user using JOPtionPane or System.console().readPassword();
                // I'm just hard coding the password, but in real it's not good.
                char password[] = new char[]{'t','e','s','t'};
                output.write(password);
                output.write('\n');
                output.flush();
                // erase password data, to avoid security issues.
                Arrays.fill(password, '\0');
                tryies++;
            }
        }

        return tryies < 3;
    } catch (IOException ex) {
    }

    return false;
}
于 2016-11-23T23:33:34.217 回答
7

不要尝试在文件中明确写入系统密码,特别是对于具有 sudo 权限的用户,正如@jointEffort 回答的那样,颁发的权限应该由系统管理员而不是应用程序编写者来解决。

sudo允许您将特定命令的权限授予特定用户,这已经足够了,请查看这篇文章

如果您只想追加到主文件中(大多数 Linux 发行版已经这样做了)并制作如下文件,则可以选择在主sudoers文件以外的单独文件中管理权限并制作如下文件:#includedirs /etc/sudoers.d//etc/sudoersifconfig-user

 USER_NAME ALL=(ALL) NOPASSWD: /sbin/ifconfig

另一件事,请记住编辑配置文件,visudo以防在出现语法错误时失去对系统的控制。

于 2017-02-07T12:53:26.077 回答
2

我知道这是一个旧线程,但我只想把它放在这里:

您可以将sudo -S *command*其用作创建 Process 实例的命令。然后获取输出流并将密码写入其中,并在其末尾添加一个新行和一个 c。返回 ( \n\r)。可能不需要退货,但我通过它以防万一。刷新流也是一个好主意,以确保将所有内容都写入其中。我已经做了几次,它就像一个魅力。并且不要忘记关闭流:)。

于 2015-01-19T08:20:37.340 回答
1

生成进程后,您可以提取输入和输出流。只需将密码输入输出流(将其输出到进程的输入中)。所以代码看起来像 -

Process pb = new ProcessBuilder("gedit").start();
OutputStream out = pb.getOutputStream();
out.write(password);
于 2013-09-09T22:52:06.583 回答