我正在尝试在JAVA中执行一个简单的关机程序,我无法相信我无法在其他任何地方找到答案。
我首先尝试在我的java程序中使用sudo:
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class themain{
public static void main(String[] args){
Process ls=null;
BufferedReader input=null;
String line=null;
String[] cmd = {"sudo shutdown -h +20"};
try {
ls= Runtime.getRuntime().exec(cmd);
input = new BufferedReader(new InputStreamReader(ls.getInputStream()));
} catch (IOException e1) {
e1.printStackTrace();
System.exit(1);
}
try {
while( (line=input.readLine())!=null)
System.out.println(line);
} catch (IOException e1) {
e1.printStackTrace();
System.exit(0);
}
}
}
然后我尝试使用此代码执行shell脚本:
sudo shutdown -h +20
新的java程序现在看起来像这样:
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class themain{
public static void main(String[] args){
Process ls=null;
BufferedReader input=null;
String line=null;
String[] cmd = {"sh shutdown.sh"};
try {
ls= Runtime.getRuntime().exec(cmd);
input = new BufferedReader(new InputStreamReader(ls.getInputStream()));
} catch (IOException e1) {
e1.printStackTrace();
System.exit(1);
}
try {
while( (line=input.readLine())!=null)
System.out.println(line);
} catch (IOException e1) {
e1.printStackTrace();
System.exit(0);
}
}
}
这当然也不起作用......无论如何我可以调用密码图形密码提示吗?我希望这个程序可以在每台计算机上运行,所以我不想搞砸我个人的sudoers文件......
问候,谢谢
答案 0 :(得分:2)
注意this thread,特别是:
“sudo”的密码需要通过键盘或键盘显示 它需要通过SUDO_ASKPASS定义的过程呈现 环境变量使用“sudo -A”。通过调用您的脚本 Java您的脚本无法访问键盘,因此您必须设置 环境变量指向返回密码的程序 以“\ n”结尾。而不是直接使用'sudo',你可以使用 'gksudo'会弹出一个对话框提示用户 密码。这是我的首选解决方案。
答案 1 :(得分:0)
package me.barwnikk.library.linuxcommandroot;
import java.awt.BorderLayout;
import java.io.IOException;
import java.io.InputStream;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
public class LinuxCommand {
static InputStream is;
static byte[] buff = new byte[8192];
static int n;
public static String getPasswdForRoot() throws IOException {
Process p = Runtime.getRuntime().exec(new String[]{"sh","-c","sudo -S id"});
is = p.getErrorStream();
n = is.read(buff, 0, 8192);
String text = new String(buff,0,n);
if(text.contains("root"))return null; //not set password
JPanel panel = new JPanel(new BorderLayout());
JLabel lab = new JLabel(text);
panel.add(lab,BorderLayout.NORTH);
JPasswordField password = new JPasswordField();
panel.add(password,BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null, panel);
byte[] passwd = (new String(password.getPassword())+"\r\n").getBytes();
p.getOutputStream().write(passwd);
p.getOutputStream().flush();
n = is.read(buff, 0, 8192);
if(n==-1) return new String(password.getPassword());
text = new String(buff,0,n);
while(true) {
lab.setText(text);
JOptionPane.showMessageDialog(null, panel);
p = Runtime.getRuntime().exec(new String[]{"sh","-c","sudo -S id"});
is = p.getErrorStream();
n = is.read(buff, 0, 8192);
passwd = (new String(password.getPassword())+"\n").getBytes();
p.getOutputStream().write(passwd);
p.getOutputStream().flush();
n = is.read(buff, 0, 8192);
if(n==-1) return new String(password.getPassword());
text = new String(buff,0,n);
}
}
public static Process runFromRoot(String command, String password) throws IOException {
byte[] passwd = (password+"\n").getBytes(); //for OutputStream better is byte[]
Process p = Runtime.getRuntime().exec(new String[]{"sh","-c","sudo -S "+command});
p.getOutputStream().write(passwd);
p.getOutputStream().flush();
return p;
}
}
获取root密码是一个迷你API(用户必须写正确)。用法示例:
public static void main(String[] args) throws IOException, InterruptedException {
String password = LinuxCommand.getPasswdForRoot();
System.out.println("stdout of 'id':");
Process p = LinuxCommand.runFromRoot("id",password);
System.out.print(streamToString(p.getInputStream()));
System.out.println("stdout of 'fdisk -l':");
p = LinuxCommand.runFromRoot("fdisk -l",password);
System.out.print(streamToString(p.getInputStream()));
}
方法streamToString:
public static String streamToString(InputStream stream) {
String read = "";
try {
while((n=stream.read(buff, 0, 8192))!=-1) {
read+=new String(buff,0,n);
}
} catch (IOException e) {
e.printStackTrace();
}
return read;
}
我的测试中的样品返回(抛光):
stdout of 'id':
uid=0(root) gid=0(root) grupy=0(root)
stdout of 'fdisk -l':
Disk /dev/sda: 640.1 GB, 640135028736 bytes
głowic: 255, sektorów/ścieżkę: 63, cylindrów: 77825, w sumie sektorów: 1250263728
Jednostka = sektorów, czyli 1 * 512 = 512 bajtów
Rozmiar sektora (logiczny/fizyczny) w bajtach: 512 / 4096
Rozmiar we/wy (minimalny/optymalny) w bajtach: 4096 / 4096
Identyfikator dysku: 0xc56b9eef
Urządzenie Rozruch Początek Koniec Bloków ID System
/dev/sda1 2048 37064703 18531328 27 Hidden NTFS WinRE
/dev/sda2 * 37064704 37269503 102400 7 HPFS/NTFS/exFAT
/dev/sda3 37269504 456711884 209721190+ 7 HPFS/NTFS/exFAT
/dev/sda4 456711946 1250258624 396773339+ f W95 Rozsz. (LBA)
Partycja 4 nie zaczyna się na granicy bloku fizycznego.
/dev/sda5 456711948 810350729 176819391 7 HPFS/NTFS/exFAT
Partycja 5 nie zaczyna się na granicy bloku fizycznego.
/dev/sda6 810350793 862802954 26226081 7 HPFS/NTFS/exFAT
Partycja 6 nie zaczyna się na granicy bloku fizycznego.
/dev/sda7 862803018 1020078408 78637695+ 83 Linux
Partycja 7 nie zaczyna się na granicy bloku fizycznego.
/dev/sda8 1020079368 1229791814 104856223+ 7 HPFS/NTFS/exFAT
/dev/sda9 1229791878 1250258624 10233373+ 7 HPFS/NTFS/exFAT
Partycja 9 nie zaczyna się na granicy bloku fizycznego.
对你:
LinuxCommand.runFromRoot("shutdown -h 20",getPasswdForRoot());
此api创建并写入Process密码。