[英]Android Java Runtime.exec(“su”) hangs (Device Problem? works fine on other devices)
我在我的 android 應用程序上運行 tcpdump 命令,這需要 root 權限。 突然之間,“su”命令后跟一系列命令(任何命令不僅是示例)導致進程掛起(process.waitFor() 永遠等待)。 它工作正常,而且問題出在哪里,我嘗試回滾到以前工作的版本並且問題仍然存在。
我正在使用 Redmi Note 4X 規格:Android 版本:6.0 MRA58K | MIUI 版本:MIUI Global 10.2.1.0(不知道還需要什么)
我嘗試在沒有 root 的情況下運行它並讀取錯誤 stream 工作正常它會產生一個錯誤,說我沒有權限(它假設)。 我曾嘗試手動殺死一些進程,認為可能有一些僵屍進程阻塞了新進程 stream,但我不知道是什么問題。 我試過用谷歌搜索答案,但它們主要是指獲取 output。 我已經嘗試過 adb shell 中的命令,它工作得很好。
java
BufferedReader in = null;
Process process = null;
try {
process = Runtime.getRuntime().exec("su");
DataOutputStream cmd = new DataOutputStream(process.getOutputStream());
cmd.writeBytes("tcpdump --version\n");
cmd.flush();
cmd.writeBytes("exit\n");
cmd.flush();
in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
process.waitFor();
if(in.ready()){
line = in.readLine();
}
if(line != null){
Log.d(TAG, line);
}else{
Log.d(TAG, "NO OUTPUT!");
}
in.close();
} catch (IOException e) {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
}
}
} catch (InterruptedException e) {
if(in != null){
try{
in.close();
} catch (IOException ex) { }
}
}finally {
if(process != null){
process.destroy();
}
}
我希望進程結束,但線程卡在 process.waitFor() 上。
更新 1.0 我已經按照建議實現了 ProcessBuilder。 但是,日志中沒有 output 並且主線程仍然掛起(p.waitFor() 永遠等待)。 正如我已經說過的,“su”命令不會在我正在測試的環境中請求任何密碼。 它正在使用 Droid4X 模擬器。
private void updateSpinner(){
BufferedReader in = null;
Process p = null;
try {
ProcessBuilder processBuilder = new ProcessBuilder("su", "tcpdump", "--version");
processBuilder.redirectErrorStream(true);
p = processBuilder.start();
in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
Log.d(TAG, line);
}
in.close();
int exitCode = p.waitFor();
} catch (IOException e) {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
}
}
} catch (InterruptedException e) {
if(in != null){
try{
in.close();
} catch (IOException ex) { }
}
}finally {
if(p != null){
p.destroy();
}
}
您可能使用了錯誤的命令。 su
命令說明如下:
“
su
命令用於在登錄 session 期間成為另一個用戶。”
但是您在這里擁有的不是登錄session。
“如果合適,將提示用戶輸入密碼。”
在您的情況下,由於您嘗試su
到root
,因此su
命令將提示輸入root
密碼。 您的 Java 代碼未發送密碼。 這可能就是為什么su
掛了!
所以讓我們退后一步。
使用su
執行此操作是個壞主意。 您的 Java 應用程序將需要“知道”根密碼。 這意味着它必須存儲在程序可以獲取它的地方。 由於該程序此時將是無特權的,這會帶來很大的安全問題。
一個更好的主意是使用sudo
。 sudo
命令將單個命令作為特權命令執行; 例如sudo ls -l
ls -l
。 通常,它會提示輸入密碼,但是:
可以配置sudo
以使某些用戶或命令組不受此限制,並且
您可以將密碼作為命令行選項傳遞給sudo
。
也可以配置sudo
使某些用戶只能以root
身份執行某些命令。 閱讀man sudo
和man sudoers
了解詳細信息。
因此,如果您要使用來自 Java 的sudo tcpdump --version
(並且您已經處理了密碼和權限控制問題),您只需要執行以下操作:
Process p = new ProcessBuilder("sudo", "tcpdump", "--version").start();
Reader in = new InputStreamReader(p.getInputStream());
// read the version string from the processes stdout
in.close();
int exitCode = p.waitFor();
請注意, ProcessBuilder
允許您做更多的事情; 請參閱javadoc 。
如果您需要運行多個命令,請考慮編寫 shell 腳本來執行它們,然后sudo
腳本。 (但要警惕有人可以通過環境變量改變 shell 腳本的行為的各種詭計。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.