Android .exec 使用方法

时间:2025-01-28 08:02:54

Android ().exec() 使用方法

苍痕 2015-04-08 15:05:01  26143  收藏 5
版权
Android 可以通过().exec()方法来执行命令或者创建进程。

1. ().exec共有六个重载方法:

public Process exec(String command)

在单独的进程中执行指定的字符串命令。

public Process exec(String [] cmdArray)

        在单独的进程中执行指定命令和变量

public Process exec(String command, String [] envp)

在指定环境的独立进程中执行指定命令和变量

public Process exec(String [] cmdArray, String [] envp)

在指定环境的独立进程中执行指定的命令和变量

public Process exec(String command,String[] envp,File dir)

在有指定环境和工作目录的独立进程中执行指定的字符串命令

public Process exec(String[] cmdarray,String[] envp,File dir)

在指定环境和工作目录的独立进程中执行指定的命令和变量

我们先来比较exec(String command)与exec(String[] cmdArray)的区别,其实他们是等价的,最终都会调用:

exec(String[] cmdarray,String[] envp,File dir),我们看看方法exec(String cmdarray,String[] envp,File dir) throws IOException的实现代码:

public Process exec(String command, String[] envp, File dir) throws IOException {
    if (() == 0) throw new IllegalArgumentException("Empty command");
    StringTokenizer st = new StringTokenizer(command);
    String[] cmdarray = new String[()];
    for (int i = 0; (); i++) {
        cmdarray[i] = ();
    }
    return exec(cmdarray, envp, dir);
}
从上面的代码,我们可以看出最终调用的代码都是:exec(String[] cmdArray,String envp,File  dir)。exec(String command)相当于exec(command,null,null),exec(String[] cmdArray)相当于exec(cmdArray,null,null)。
2. 参数说明:

cmdarray- 包含所调用命令及其参数的数组

envp- 字符串数组,其中每个元素的环境变量的设置格式为 name=value,如果子进程应该继承当前进程的环境,或该参数为 null

dir- 子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为 null

3. 关于返回结果类型:Process,它有几个方法:

    (1).destroy():杀掉子进程

    (2).exitValue():返回子进程的出口值,值0表示正常终止

    (3).getErrorStream():获取子进程的错误流

    (4).getInputStream():获取子进程的输入流

    (5).getOutputStream():获取子进程的输出流

    (6).waitFor():导致当前线程等待,如有必要,一直要等到由该Process对象表示的进程已经终止。如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程,根据惯例, 0表示正常终止

4. 如何获取command 最终执行的结果?
    (1) 执行command命令,将命令行输出重定向到一个文件,再读取文件判断执行结果。

        比如命令:javap -l xxx >   , 调用exec(String[] cmdArray)如下:

Process p = ().exec(new String[]{"/bin/sh","-c", "javap -l xxx > "});
   (2) 也可以通过InputStream/OutputStream, 获取命令执行的结果。

        下面例子是先利用“su”提权,然后执行command,完整代码:


    private static boolean exeCommand(String command) {
        boolean ret = false;
        try {
            VirtualTerminal vt;
            vt = new VirtualTerminal("su");
            VTCommandResult r = (command);
            ret = ();
            ();
        } catch (Exception e) {
            ();
        }
 
        return ret;
    }

package ;
 
import ;
import ;
import ;
import ;
 
import ;
 
public class VirtualTerminal {
 
    private static final String TAG = "VirtualTerminal";
 
    private final Object mReadLock = new Object();
    private final Object mWriteLock = new Object();
    private Process mProcess = null;
 
    private DataOutputStream mOutputStream;
    private ByteArrayOutputStream mInputBuffer = new ByteArrayOutputStream();
    private ByteArrayOutputStream mErrBuffer = new ByteArrayOutputStream();
    private InputReaderThread mInputReaderThread;
    private InputReaderThread mErrReaderThread;
 
    public VirtualTerminal(String shell) throws IOException, InterruptedException {
        
        mProcess = ().exec(shell);
        
        mOutputStream = new DataOutputStream(());
 
        mInputReaderThread = new InputReaderThread((), mInputBuffer);
        mErrReaderThread = new InputReaderThread((), mErrBuffer);
        (50);
        ();
        ();
    }
 
    public VTCommandResult runCommand(String command) throws Exception {
        synchronized (mWriteLock) {
            ();
            ();
        }
 
        // $? 表示最后运行的命令的结束代码(返回值)
        (command + "\necho :RET=$?\n");
        ();
        
        while (true) {
            synchronized (mReadLock) {
                boolean doWait = false;
                synchronized (mWriteLock) {
                    byte[] inpbyte = ();
                    String inp = new String(inpbyte);
                    doWait = !(":RET=");
                }
                if (doWait) {
                    ();
                }
            }
 
            synchronized (mWriteLock) {
                byte[] inpbyte = ();
                byte[] errbyte = ();
                String inp = new String(inpbyte);
                String err = new String(errbyte);
 
                //Please keep log statement or else it will dead loop
                if ((":RET=")) {
                    if ((":RET=EOF") || (":RET=EOF")) {
                        (TAG, "exec:[eof]" + inp);
                    }
                    
                    if ((":RET=0")) {
                        (TAG, "exec:[ok]" + inp);
                        return new VTCommandResult(0, inp, err);
                    } else {
                        (TAG, "exec:[err]" + inp);
                        return new VTCommandResult(1, inp, err);
                    }
                }
            }
        }
    }
 
    public void shutdown() {
        ();
        ();
        ();
    }
 
    /**
     * A thread class helps to read/write data
     */
    public class InputReaderThread extends Thread {
        private InputStream mInputStream;
        private ByteArrayOutputStream mByteArrayOutputStream;
 
        public InputReaderThread(InputStream in, ByteArrayOutputStream out) {
            mInputStream = in;
            mByteArrayOutputStream = out;
        }
 
        @Override
        public void run() {
            if (mInputStream != null) {
                try {
                    byte[] buffer = new byte[1024];
                    while (true) {
                        int read = (buffer);
                        if (read < 0) {
                            synchronized(mWriteLock) {
                                String eof = ":RET=EOF";
                                (());
                            }
                            synchronized (mReadLock) {
                                ();
                            }
 
                            break;
                        } else if (read > 0) {
                            synchronized(mWriteLock) {
                                (buffer, 0, read);
                            }
                            synchronized (mReadLock) {
                                ();
                            }
                        }
                    }
                } catch (Exception ex) {
                    ();
                }
            }
        }
    }
 
    /**
     * A result wrapper for exec()
     */
    public class VTCommandResult {
        public final String mStdout;
        public final String mStderr;
        public final Integer mExitValue;
 
        VTCommandResult(Integer exit_value_in, String stdout_in, String stderr_in) {
            mExitValue = exit_value_in;
            mStdout = stdout_in;
            mStderr = stderr_in;
        }
 
        VTCommandResult(Integer exit_value_in) {
            this(exit_value_in, null, null);
        }
 
        public boolean success() {
            return mExitValue != null && mExitValue == 0;
        }
    }
}
5. 如何用Worker thread 实现 exec() 的等待超时机制?


  /**
     * 运行一个外部命令,返回状态, 可以设置超时时间
     * @param command
     * @param timeout, in milliseconds
     * @return
     */
    private int execCommand(final String[] commandArray, final long timeout) {
        Worker worker = null;
        try {
            worker = new Worker(commandArray);
            ();
            (timeout);
        } catch (Throwable t) {
            ();
        } finally {
            if ( != Integer.MAX_VALUE) {
                return ;
            } else {
                ();
            }  
        }
        return ErrorCodeDefine.DOROOT_FAIL;
    }
 
    /**
     * 用Worker thread 可以实现超时机制
     */
    private static class Worker extends Thread {
        private final String[] commandArray;
        private int exit = Integer.MAX_VALUE;
 
        private Worker(String[] commandArray) {
            = commandArray;
        }
 
        public void run() {
            Process process = null;
            try {
                process = ().exec(commandArray);
                if (process != null) {
                    exit = ();
                }
            } catch (InterruptedException e) {
                ();
            } catch (Throwable t) {
                ();
            } finally {
                if (process != null) {
                    killProcess(process);
                }
            }
        }
    }
 
    /**
     * 通过Android底层实现进程关闭
     */
    private static void killProcess(Process process) {
        int pid = getProcessId(());
        if (pid != 0) {
            try {
                closeAllStream(process);
                (pid);
            } catch (Exception e) {
                try {
                    ();
                } catch (Exception ex) {
                    ();
                }
            }
        }
    }
 
    /**
     * 获取当前进程的ID
     */
    private static int getProcessId(String str) {
        try {
            int i = ("=") + 1;
            int j = ("]");
            String cStr = (i, j).trim();
            return (cStr);
        } catch (Exception e) {
            return 0;
        }
    }
 
    /**
     * 关闭进程的所有流
     *
     * @param process
     */
    public static void closeAllStream(Process process) {
        try {
            InputStream in = ();
            if (in != null)
                ();
        } catch (Exception e) {
            ();
        }
        try {
            InputStream in = ();
            if (in != null)
                ();
        } catch (Exception e) {
            ();
        }
        try {
            OutputStream out = ();
            if (out != null)
                ();
        } catch (Exception e) {
            ();
        }

————————————————
版权声明:本文为****博主「苍痕」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:/wangbaochu/article/details/44941045