Как выполнить команду 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 с последним обновлением.
6 ответов
Я думаю, что вы можете использовать это, но я немного не решаюсь опубликовать это. Так что я просто скажу:
Используйте это на свой страх и риск, не рекомендуется, не судитесь со мной и т.д....
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();
}
Отредактируйте /etc/sudoers с помощью visudo и предоставьте вашему пользователю право NOPASSWD для конкретного скрипта:
имя пользователя ALL=(ALL) NOPASSWD: /opt/yourscript.sh
Мое решение не раскрывает пароль в командной строке, оно просто передает пароль в выходной поток процесса. Это более гибкое решение, поскольку позволяет запрашивать пароль у пользователя, когда это необходимо.
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;
}
Не пытайтесь записать системный пароль прямо в файл, особенно для пользователя, у которого есть привилегия sudo, так же, как ответил @jointEffort, выданная привилегия должна решаться системными администраторами, а не авторами приложений. sudo
позволяют предоставить привилегии для конкретной команды конкретному пользователю, что достаточно точно, проверьте этот пост
и вы можете управлять привилегией в отдельном файле, отличном от основного файла sudoers, если хотите просто добавить #includedirs /etc/sudoers.d/
в основном /etc/sudoers
файл (большинство дистрибутивов Linux уже сделали это) и сделать файл как ifconfig-user
с:
USER_NAME ALL=(ALL) NOPASSWD: /sbin/ifconfig
Еще одна вещь, не забудьте отредактировать файл конфигурации с visudo
в случае, если вы потеряли контроль над вашей системой при синтаксической ошибке.
Я знаю, что это старая тема, но я просто хочу поместить это здесь:
ты можешь использовать sudo -S *command*
в качестве команды, которую вы передаете, чтобы создать экземпляр процесса. Затем получите выходной поток и напишите ему пароль, а в конце добавьте новую строку и символ c. вернуть (\n\r
). Возврат может не потребоваться, но я передал его на всякий случай. Также хорошей идеей будет очистить поток, чтобы убедиться, что все записано в него. Я сделал это несколько раз, и это работает как шарм. И НЕ забывайте закрывать потоки:).
После запуска процесса вы можете извлечь входной и выходной потоки. Просто введите пароль в выходной поток (вы выводите его на вход процесса). Таким образом, код будет выглядеть примерно так:
Process pb = new ProcessBuilder("gedit").start();
OutputStream out = pb.getOutputStream();
out.write(password);