Linux 如何在 Java 中以 sudo 权限执行 bash 命令?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18708087/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to execute bash command with sudo privileges in Java?
提问by Vare Zon
I'm using ProcessBuilder to execute bash commands:
我正在使用 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();
}
}
}
But I want to make something like this:
但我想做这样的事情:
Process pb = new ProcessBuilder("sudo", "gedit").start();
How to pass superuser password to bash?
如何将超级用户密码传递给 bash?
("gksudo", "gedit")
will not do the trick, because it was deleted since Ubuntu 13.04 and I need to do this with available by default commands.
("gksudo", "gedit")
不会成功,因为它自 Ubuntu 13.04 以来已被删除,我需要使用默认可用的命令来执行此操作。
EDIT
编辑
gksudo came back to Ubuntu 13.04 with the last update.
gksudo 在上次更新时回到了 Ubuntu 13.04。
采纳答案by Erik Pragt
I think you can use this, but I'm a bit hesitant to post it. So I'll just say:
我想你可以使用这个,但我有点犹豫要不要发布它。所以我只想说:
Use this at your own risk, not recommended, don't sue me, etc...
使用此风险自负,不推荐,不要起诉我等...
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();
}
回答by David says Reinstate Monica
Once you spawn a process you can extract the input and output streams. Just feed the password to the output stream (you output it into the proccess's input). So the code would look something like -
生成进程后,您可以提取输入和输出流。只需将密码提供给输出流(您将其输出到过程的输入中)。所以代码看起来像 -
Process pb = new ProcessBuilder("gedit").start();
OutputStream out = pb.getOutputStream();
out.write(password);
回答by mcrius
I know this is an old thread but i just want to put this here:
我知道这是一个旧线程,但我只想把它放在这里:
you can use sudo -S *command*
as a command that you pass to create the Process instance. Then get the output stream and write the password to it, and add at the end of it a new line and a c. return (\n\r
). The return may not be required but i passed it just in case. Also it is a good idea to flush the stream, to make sure everything is written to it. I've done it a few times and it works like a charm. And DO NOT forget to close streams :).
您可以将其sudo -S *command*
用作传递来创建 Process 实例的命令。然后获取输出流并将密码写入其中,并在其末尾添加一个新行和一个 c。返回 ( \n\r
)。可能不需要退货,但我通过了它以防万一。刷新流也是一个好主意,以确保所有内容都写入其中。我已经做了几次,它就像一个魅力。并且不要忘记关闭流:)。
回答by JointEffort
Edit /etc/sudoers with visudo and grant your user a NOPASSWD right for a specific script:
使用 visudo 编辑 /etc/sudoers 并为您的用户授予特定脚本的 NOPASSWD 权限:
username ALL=(ALL) NOPASSWD: /opt/yourscript.sh
用户名 ALL=(ALL) NOPASSWD:/opt/yourscript.sh
回答by kato2
My solution, doesn't exposes the password in the command line, it just feed the password to the output stream of the process. This is a more flexible solution because allows you to request the password to the user when it is needed.
我的解决方案没有在命令行中公开密码,它只是将密码提供给进程的输出流。这是一个更灵活的解决方案,因为允许您在需要时向用户请求密码。
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, ' USER_NAME ALL=(ALL) NOPASSWD: /sbin/ifconfig
');
tryies++;
}
}
return tryies < 3;
} catch (IOException ex) {
}
return false;
}
回答by armnotstrong
Do not try to write a system password plainly in a file, especially for a user that have the sudo privilage, just as @jointEffort answered, privilege issued should be solved by system administrators not by app writers. sudo
allow you to grant privileges for specific command to specific user, which is precisely enough, check this post
不要试图在文件中简单地写系统密码,特别是对于具有 sudo 权限的用户,正如@jointEffort 回答的那样,权限发布应该由系统管理员解决,而不是由应用程序编写者解决。sudo
允许您将特定命令的权限授予特定用户,这就足够了,请查看此帖子
and you can choose to manage the privilege in a separated file other than the main sudoers file if you want just append #includedirs /etc/sudoers.d/
in the main /etc/sudoers
file(most Linux distributions have already done that) and make a file like ifconfig-user
with:
如果您只想附加#includedirs /etc/sudoers.d/
到主/etc/sudoers
文件中(大多数 Linux 发行版已经这样做了),并且您可以选择在主 sudoers 文件以外的单独文件中管理权限并创建一个文件,例如ifconfig-user
:
Another thing, remember to edit the config file with visudo
in case you lost control of your system when there is syntax error.
另一件事,请记住编辑配置文件,visudo
以防在出现语法错误时失去对系统的控制。