【问题标题】:Read command output inside su process在 su 进程中读取命令输出
【发布时间】:2011-10-17 07:39:20
【问题描述】:

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

问题来了。如何读取“ls”进程的输出?我所拥有的只是“su” Process 对象。从中获取输入流什么也没有,因为“su”不写任何东西。但是“ls”可以,我不知道如何访问它的输出消息。

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

问候

【问题讨论】:

    标签: android root su


    【解决方案1】:

    好的,我找到了解决方案。它应该是这样的:

    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
    

    希望对某人有所帮助

    【讨论】:

    • 如果系统调用没有返回任何内容,对 read() 的调用就会停止。在这种特殊情况下,“ls”应该总是返回一些东西,但请记住它可能会与其他命令一起停止。
    • @glodos 有没有办法在不指定 BUFF_LEN 的情况下做到这一点?也就是说,一次读一行,直到没有更多行?
    • 嗨,我一直在成功使用您的示例,但我很难让它在 Android Nougat 上运行。有人对此有任何想法吗?
    • 调用 Runtime.getRuntime().exec("su");对我来说似乎已经足够了,因为 su 二进制文件可能会自行启动一个 shell。
    【解决方案2】:
    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;
    }
    

    检查这里提到的这段代码:

    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);
    }
    

    参考文献

    this code GScript

    【讨论】:

    • 此代码不起作用。没有像“android.os.Exec”这样的类。我已经读到它不再适用于 Froyo 及更高版本。
    • 我尝试了类似的方法,但在命令前使用了“su”,但随后系统会要求每次执行都与以前有所不同(例如列出另一个目录)。我需要做的就是只获得一次“su”命令的权限(用户点击记住,系统不再询问),然后在这个进程中执行我的命令并读取它们的输出。明确一点:1.创建su进程。 2. 将“ls”命令写入输出流(ls 以su 权限执行)。 3. 读取“ls”输出。我无法达到第 3 点
    【解决方案3】:

    我针对以下问题修改了@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 {
          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();
      }
      

    一些学分归@Sherif elKhatib ))

    【讨论】:

    • 不幸的是,这对我不起作用......我只是没有得到任何结果。
    猜你喜欢
    • 2012-06-30
    • 1970-01-01
    • 2017-12-15
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 2013-01-04
    • 1970-01-01
    相关资源
    最近更新 更多