Как выполнить команду bash с привилегиями sudo в Java?

Я использую 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 с последним обновлением.

Ответы

Ответ 1

Я думаю, вы можете использовать это, но я немного не решаюсь его опубликовать. Поэтому я просто скажу:

Используйте это на свой страх и риск, не рекомендуется, не подавайте на меня и т.д.

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();
}

Ответ 2

Измените/etc/sudoers с visudo и дайте своему пользователю право NOPASSWD для определенного script:

имя пользователя ALL = (ВСЕ) NOPASSWD:/opt/yourscript.sh

Ответ 3

Мое решение не предоставляет пароль в командной строке, он просто передает пароль в выходной поток процесса. Это более гибкое решение, поскольку позволяет запрашивать пароль пользователю, когда это необходимо.

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 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;
}

Ответ 4

Как только вы создадите процесс, вы можете извлечь потоки ввода и вывода. Просто подайте пароль в выходной поток (вы выводите его на вход proccess). Таким образом, код будет выглядеть примерно так:

Process pb = new ProcessBuilder("gedit").start();
OutputStream out = pb.getOutputStream();
out.write(password);

Ответ 5

Я знаю, что это старый поток, но я просто хочу поставить это здесь:

вы можете использовать sudo -S *command* в качестве команды, которую вы передаете, чтобы создать экземпляр процесса. Затем получите выходной поток и напишите ему пароль, а затем добавьте в него новую строку и c. return (\n\r). Возврат может не потребоваться, но я передал его на всякий случай. Также рекомендуется очистить поток, чтобы убедиться, что все написано на нем. Я делал это несколько раз, и это работает как шарм. И НЕ забывайте закрывать потоки:).

Ответ 6

Не пытайтесь писать системный пароль прямо в файле, особенно для пользователя, обладающего привилегией sudo, точно так же, как @jointEffort ответил, выдача привилегий должна решаться системными администраторами не писателями приложений. sudo позволяет вам предоставлять привилегии для конкретной команды конкретному пользователю, что достаточно точно, отметьте этот пост

и вы можете выбрать управление привилегией в отдельном файле, отличном от основного файла sudoers, если вы хотите просто добавить #includedirs /etc/sudoers.d/ в основной файл /etc/sudoers (большинство дистрибутивов Linux уже сделали это) и создать файл как ifconfig-user с помощью:

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

Другое дело, не забудьте отредактировать конфигурационный файл с visudo, если вы потеряли контроль над своей системой при наличии синтаксической ошибки.