Read command output inside su process

后端 未结 3 711
余生分开走
余生分开走 2020-11-28 08:05

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 do

相关标签:
3条回答
  • 2020-11-28 08:07
    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

    0 讨论(0)
  • 2020-11-28 08:15

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

    0 讨论(0)
  • 2020-11-28 08:32

    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

    0 讨论(0)
提交回复
热议问题