读取 su 进程内的命令输出

发布于 2024-11-27 09:55:59 字数 255 浏览 1 评论 0原文

首先我介绍一下我的情况。 我需要在我的 Android 应用程序中执行“su”命令,它运行良好。然后我需要执行“ls”命令并读取输出。我通过从“su”进程获取输出流并将我的命令写入其中来完成此操作。

问题来了。如何读取“ls”进程的输出?我所拥有的只是“su”进程对象。从中获取输入流不会给出任何结果,因为“su”不写任何内容。但“ls”确实如此,但我不知道如何访问其输出消息。

我搜索了很多网站,但没有找到任何解决方案。也许有人会帮助我:)

问候

firstly I will present my situation.
I need to execute "su" command in my android app and it works well. Then I need to execute "ls" command and read the output. I'm doing it by getting the output stream from the "su" process and writing my command into it.

And here goes the question. How to read the output of the "ls" process? All I have is the "su" Process object. Getting the input stream from it gives nothing, because "su" doesn't write anything. But "ls" does and I don't know how to access its output messages.

I have searched many sites but I didn't find any solution. Maybe someone will help me:)

Regards

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

辞取 2024-12-04 09:55:59

好的,我找到了解决方案。它应该看起来像这样:

Process p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
DataOutputStream stdin = new DataOutputStream(p.getOutputStream());
//from here all commands are executed with su permissions
stdin.writeBytes("ls /data\n"); // \n executes the command
InputStream stdout = p.getInputStream();
byte[] buffer = new byte[BUFF_LEN];
int read;
String out = new String();
//read method will wait forever if there is nothing in the stream
//so we need to read it in another way than while((read=stdout.read(buffer))>0)
while(true){
    read = stdout.read(buffer);
    out += new String(buffer, 0, read);
    if(read<BUFF_LEN){
        //we have read everything
        break;
    }
}
//do something with the output

希望对某人有帮助

Ok, I've found a solution. It should look like this:

Process p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
DataOutputStream stdin = new DataOutputStream(p.getOutputStream());
//from here all commands are executed with su permissions
stdin.writeBytes("ls /data\n"); // \n executes the command
InputStream stdout = p.getInputStream();
byte[] buffer = new byte[BUFF_LEN];
int read;
String out = new String();
//read method will wait forever if there is nothing in the stream
//so we need to read it in another way than while((read=stdout.read(buffer))>0)
while(true){
    read = stdout.read(buffer);
    out += new String(buffer, 0, read);
    if(read<BUFF_LEN){
        //we have read everything
        break;
    }
}
//do something with the output

Hope it will be helpful for someone

つ可否回来 2024-12-04 09:55:59
public String ls () {
    Class<?> execClass = Class.forName("android.os.Exec");
    Method createSubprocess = execClass.getMethod("createSubprocess", String.class, String.class, String.class, int[].class);
    int[] pid = new int[1];
    FileDescriptor fd = (FileDescriptor)createSubprocess.invoke(null, "/system/bin/ls", "/", null, pid);

    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fd)));
    String output = "";
    try {
        String line;
        while ((line = reader.readLine()) != null) {
            output += line + "\n";
        }
    }
    catch (IOException e) {}
    return output;
}

检查此处提到的代码:

如何运行终端命令Android 应用程序?


try {
// Executes the command.
Process process = Runtime.getRuntime().exec("/system/bin/ls /sdcard");

// Reads stdout.
// NOTE: You can write to stdin of the command using
//       process.getOutputStream().
BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
    output.append(buffer, 0, read);
}
reader.close();

// Waits for the command to finish.
process.waitFor();

return output.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}

参考文献

这段代码
GScript

public String ls () {
    Class<?> execClass = Class.forName("android.os.Exec");
    Method createSubprocess = execClass.getMethod("createSubprocess", String.class, String.class, String.class, int[].class);
    int[] pid = new int[1];
    FileDescriptor fd = (FileDescriptor)createSubprocess.invoke(null, "/system/bin/ls", "/", null, pid);

    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fd)));
    String output = "";
    try {
        String line;
        while ((line = reader.readLine()) != null) {
            output += line + "\n";
        }
    }
    catch (IOException e) {}
    return output;
}

Check this code mentioned here:

How to run terminal command in Android application?


try {
// Executes the command.
Process process = Runtime.getRuntime().exec("/system/bin/ls /sdcard");

// Reads stdout.
// NOTE: You can write to stdin of the command using
//       process.getOutputStream().
BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
    output.append(buffer, 0, read);
}
reader.close();

// Waits for the command to finish.
process.waitFor();

return output.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}

References

this code
GScript

可爱暴击 2024-12-04 09:55:59

我针对以下问题修改了 @glodos 接受的答案:

  1. 流已关闭,否则 exec 进程将永远挂起在打开的流上。如果你在shell中执行ps(即adb shell
    多次执行后,您将看到几个 su 进程
    活。他们需要被正确终止。
  2. 添加了 waitFor() 以确保进程终止。
  3. 添加了对 read=-1 的处理,现在可以执行带有空 stdout 的命令。以前,它们在 new String(buffer, 0, read) 上崩溃。
  4. 使用 StringBuffer 进行更高效的字符串处理。

    private String execCommand(String cmd) throws IOException, InterruptedException {
        进程 p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
        DataOutputStream stdout = new DataOutputStream(p.getOutputStream());
    
        stdout.writeBytes(cmd);
        stdout.writeByte('\n');
        stdout.flush();
        stdout.close();
    
        BufferedReader stdin = new BufferedReader(new InputStreamReader(p.getInputStream()));
        char[]缓冲区=新char[1024];
        整型读取;
        StringBuffer out = new StringBuffer();
    
        while((读取 = stdin.read(buffer)) > 0) {
            out.append(缓冲区, 0, 读取);
        }
        stdin.close();
        p.waitFor();
        返回out.toString();
    }
    

一些积分归@Sherif elKhatib ))

I modified accepted answer by @glodos for following problems:

  1. the streams are closed, otherwise the exec process hangs forever, on the opened stream. If you execute ps in shell (ie adb shell)
    after several executions then you'll see several su processes
    alive. They needs to be properly terminated.
  2. added waitFor() to make sure the process is terminated.
  3. Added handling for read=-1, now commands with empty stdout can be executed. Previously they crashed on new String(buffer, 0, read)
  4. Using StringBuffer for more efficient strings handling.

    private String execCommand(String cmd) throws IOException, InterruptedException {
        Process p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
        DataOutputStream stdout = new DataOutputStream(p.getOutputStream());
    
        stdout.writeBytes(cmd);
        stdout.writeByte('\n');
        stdout.flush();
        stdout.close();
    
        BufferedReader stdin = new BufferedReader(new InputStreamReader(p.getInputStream()));
        char[] buffer = new char[1024];
        int read;
        StringBuffer out = new StringBuffer();
    
        while((read = stdin.read(buffer)) > 0) {
            out.append(buffer, 0, read);
        }
        stdin.close();
        p.waitFor();
        return out.toString();
    }
    

Some credits go to @Sherif elKhatib ))

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文