不灭的焱

革命尚未成功,同志仍须努力下载JDK17

作者:Albert.Wen  添加时间:2022-03-13 19:17:53  修改时间:2024-04-23 20:23:17  分类:Java框架/系统  编辑

1、Api介绍

以下是ShellUtils中最终执行命令的方法execCommand

public CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg)

其中

  1. commands:表示依次执行的shell命令数组
  2. isRoot:表示是否以su用户执行(需要手机已经root)
  3. isNeedResultMsg:表示是否存储命令执行成功及失败后的信息。
/**
 * result of command
 * 
 * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16
 */
public static class CommandResult {

	/** result of command **/
	public int    result;
	/** success message of command result **/
	public String successMsg;
	/** error message of command result **/
	public String errorMsg;

	public CommandResult(int result){
		this.result = result;
	}

	public CommandResult(int result, String successMsg, String errorMsg){
		this.result = result;
		this.successMsg = successMsg;
		this.errorMsg = errorMsg;
	}
}
  • CommandResult:为返回的数据结构,如下其中result表示执行的结果,根据Linux命令执行规则,0表示成功,其他为相应错误码。
  • successMsg:存储执行成功后的输出信息,errorMsg存储执行失败后的输出信息。
  • 如果isNeedResultMsg为false,successMsg和errorMsg会始终为空,而result依然为正常结果。

 

其他接口,Shell命令支持执行String(单个命令), List(多个命令),String[](多个命令)

见:ShellUtils.java#Api Guide

ShellUtil.java

package cn.trinea.android.common.util;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

/**
 * ShellUtils
 * <ul>
 * <strong>Check root</strong>
 * <li>{@link ShellUtils#checkRootPermission()}</li>
 * </ul>
 * <ul>
 * <strong>Execte command</strong>
 * <li>{@link ShellUtils#execCommand(String, boolean)}</li>
 * <li>{@link ShellUtils#execCommand(String, boolean, boolean)}</li>
 * <li>{@link ShellUtils#execCommand(List, boolean)}</li>
 * <li>{@link ShellUtils#execCommand(List, boolean, boolean)}</li>
 * <li>{@link ShellUtils#execCommand(String[], boolean)}</li>
 * <li>{@link ShellUtils#execCommand(String[], boolean, boolean)}</li>
 * </ul>
 * 
 * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16
 */
public class ShellUtils {

    public static final String COMMAND_SU       = "su";
    public static final String COMMAND_SH       = "sh";
    public static final String COMMAND_EXIT     = "exit\n";
    public static final String COMMAND_LINE_END = "\n";

    private ShellUtils() {
        throw new AssertionError();
    }

    /**
     * check whether has root permission
     * 
     * @return
     */
    public static boolean checkRootPermission() {
        return execCommand("echo root", true, false).result == 0;
    }

    /**
     * execute shell command, default return result msg
     * 
     * @param command command
     * @param isRoot whether need to run with root
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(String command, boolean isRoot) {
        return execCommand(new String[] {command}, isRoot, true);
    }

    /**
     * execute shell commands, default return result msg
     * 
     * @param commands command list
     * @param isRoot whether need to run with root
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(List<String> commands, boolean isRoot) {
        return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, true);
    }

    /**
     * execute shell commands, default return result msg
     * 
     * @param commands command array
     * @param isRoot whether need to run with root
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(String[] commands, boolean isRoot) {
        return execCommand(commands, isRoot, true);
    }

    /**
     * execute shell command
     * 
     * @param command command
     * @param isRoot whether need to run with root
     * @param isNeedResultMsg whether need result msg
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) {
        return execCommand(new String[] {command}, isRoot, isNeedResultMsg);
    }

    /**
     * execute shell commands
     * 
     * @param commands command list
     * @param isRoot whether need to run with root
     * @param isNeedResultMsg whether need result msg
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(List<String> commands, boolean isRoot, boolean isNeedResultMsg) {
        return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, isNeedResultMsg);
    }

    /**
     * execute shell commands
     * 
     * @param commands command array
     * @param isRoot whether need to run with root
     * @param isNeedResultMsg whether need result msg
     * @return <ul>
     *         <li>if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and
     *         {@link CommandResult#errorMsg} is null.</li>
     *         <li>if {@link CommandResult#result} is -1, there maybe some excepiton.</li>
     *         </ul>
     */
    public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) {
        int result = -1;
        if (commands == null || commands.length == 0) {
            return new CommandResult(result, null, null);
        }

        Process process = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;

        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
            os = new DataOutputStream(process.getOutputStream());
            for (String command : commands) {
                if (command == null) {
                    continue;
                }

                // donnot use os.writeBytes(commmand), avoid chinese charset error
                os.write(command.getBytes());
                os.writeBytes(COMMAND_LINE_END);
                os.flush();
            }
            os.writeBytes(COMMAND_EXIT);
            os.flush();

            result = process.waitFor();
            // get command result
            if (isNeedResultMsg) {
                successMsg = new StringBuilder();
                errorMsg = new StringBuilder();
                successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
                errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                String s;
                while ((s = successResult.readLine()) != null) {
                    successMsg.append(s);
                }
                while ((s = errorResult.readLine()) != null) {
                    errorMsg.append(s);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (process != null) {
                process.destroy();
            }
        }
        return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null
                : errorMsg.toString());
    }

    /**
     * result of command
     * <ul>
     * <li>{@link CommandResult#result} means result of command, 0 means normal, else means error, same to excute in
     * linux shell</li>
     * <li>{@link CommandResult#successMsg} means success message of command result</li>
     * <li>{@link CommandResult#errorMsg} means error message of command result</li>
     * </ul>
     * 
     * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16
     */
    public static class CommandResult {

        /** result of command **/
        public int    result;
        /** success message of command result **/
        public String successMsg;
        /** error message of command result **/
        public String errorMsg;

        public CommandResult(int result) {
            this.result = result;
        }

        public CommandResult(int result, String successMsg, String errorMsg) {
            this.result = result;
            this.successMsg = successMsg;
            this.errorMsg = errorMsg;
        }
    }
}

2、使用场景

以目前自己的几个场景举下例子

(1) 静默安装和卸载

这个很多朋友已经用过了Android root权限静默安装或卸载应用,原理是执行命令:pm install apkFilePath及pm uninstall packageName

具体代码可见:PackageUtils installSilent(Context context, String filePath, String pmParams)

(2) 获取系统设置->存储->首选安装位置

原理是执行命令:pm get-install-location

具体代码可见:PackageUtils getInstallLocation()

(3) Android修改hosts文件

原理是执行命令:

mount -o rw,remount /system
echo “127.0.0.1 localhost” > /etc/hosts
echo “185.31.17.184 github.global.ssl.fastly.net” >> /etc/hosts
chmod 644 /etc/hosts

代码如下:

List<String> commnandList = new ArrayList<String>();
commnandList.add("mount -o rw,remount /system");
commnandList.add("echo \"127.0.0.1 localhost\" > /etc/hosts");
commnandList.add("echo \"185.31.17.184 github.global.ssl.fastly.net\" >> /etc/hosts");
commnandList.add("chmod 644 /etc/hosts");
CommandResult result = ShellUtils.execCommand(commnandList, true);

用echo命令改hosts文件很牛逼哦,不用重启可以直接生效的哦。

(4) 拷贝文件

原理是执行命令:

mount -o rw,remount /system
cp /mnt/sdcard/xx.apk /system/app/

代码如下:

String[] commands = new String[] { "mount -o rw,remount /system", "cp /mnt/sdcard/xx.apk /system/app/" };
CommandResult result = ShellUtils.execCommand(commands, true);

注意一般拷贝文件是不需要root的,上面用root是因为需要拷贝到/system/app/下面

 

 

摘自:

Android Java执行Shell命令

https://blog.csdn.net/yubang3223111/article/details/76635528

https://github.com/Trinea/android-common/blob/master/src/cn/trinea/android/common/util/ShellUtils.java

 


 

工作中,Java后端把它改为了一个 “Linux命令行工具”助手类

package com.wanma.framework_web.helper;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * Linux命令行工具 助手类
 * 参考:/2160.html
 */
public class ShellHelper {
    public static final String COMMAND_SU = "su";
    public static final String COMMAND_SH = "sh";
    public static final String COMMAND_EXIT = "exit\n";
    public static final String COMMAND_LINE_END = "\n";

    private ShellHelper() {
        throw new AssertionError();
    }

    /**
     * 检测是否有root权限
     */
    public static boolean checkRootPermission() throws Exception {
        return exec("echo root", true, false).code == 0;
    }

    /**
     * 执行Shell命令
     *
     * @param command 单个命令行
     * @param isRoot  是否切换至root用户
     * @return CommandResult
     */
    public static CommandResult exec(String command, boolean isRoot) throws Exception {
        return exec(new String[]{command}, isRoot, true);
    }

    /**
     * 执行Shell命令
     *
     * @param commands 命令行列表
     * @param isRoot   是否切换至root用户
     * @return CommandResult
     */
    public static CommandResult exec(ArrayList<String> commands, boolean isRoot) throws Exception {
        return exec(commands == null ? null : commands.toArray(new String[]{}), isRoot, true);
    }

    public static CommandResult exec(ArrayList<String> commands) throws Exception {
        return exec(commands == null ? null : commands.toArray(new String[]{}), false, true);
    }

    /**
     * 执行Shell命令
     *
     * @param commands 命令行数组
     * @param isRoot   是否切换至root用户
     * @return CommandResult
     */
    public static CommandResult exec(String[] commands, boolean isRoot) throws Exception {
        return exec(commands, isRoot, true);
    }

    public static CommandResult exec(String[] commands) throws Exception {
        return exec(commands, false, true);
    }

    /**
     * 执行Shell命令
     *
     * @param command         单个命令行
     * @param isRoot          是否切换至root用户
     * @param isNeedResultMsg 是否需要返回结果信息
     * @return CommandResult
     */
    public static CommandResult exec(String command, boolean isRoot, boolean isNeedResultMsg) throws Exception {
        return exec(new String[]{command}, isRoot, isNeedResultMsg);
    }

    /**
     * 执行Shell命令
     *
     * @param commands        命令行列表
     * @param isRoot          是否切换至root用户
     * @param isNeedResultMsg 是否需要返回结果信息
     * @return CommandResult
     */
    public static CommandResult exec(List<String> commands, boolean isRoot, boolean isNeedResultMsg) throws Exception {
        return exec(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg);
    }

    /**
     * execute shell commands
     *
     * @param commands        命令行数组
     * @param isRoot          是否切换至root用户
     * @param isNeedResultMsg 是否需要返回结果信息
     * @return CommandResult
     * 假如isNeedResultMsg等于false,CommandResult.successMsg为null,CommandResult.errorMsg为null,
     * 假如CommandResult.code等于-1,可能发生了异常
     */
    public static CommandResult exec(String[] commands, boolean isRoot, boolean isNeedResultMsg) throws Exception {
        int code = -1;
        if (commands == null || commands.length == 0) {
            return new CommandResult(code, null, null);
        }

        Process process = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;

        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
            os = new DataOutputStream(process.getOutputStream());
            for (String command : commands) {
                if (command == null) {
                    continue;
                }

                // donnot use os.writeBytes(commmand), avoid chinese charset error
                os.write(command.getBytes());
                os.writeBytes(COMMAND_LINE_END);
                os.flush();
            }
            os.writeBytes(COMMAND_EXIT);
            os.flush();

            code = process.waitFor();
            // get command code
            if (isNeedResultMsg) {
                successMsg = new StringBuilder();
                errorMsg = new StringBuilder();
                successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
                errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                String s;
                while ((s = successResult.readLine()) != null) {
                    successMsg.append(s).append(COMMAND_LINE_END);
                }
                while ((s = errorResult.readLine()) != null) {
                    errorMsg.append(s).append(COMMAND_LINE_END);
                }
            }
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (process != null) {
                process.destroy();
            }
        }
        return new CommandResult(code, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null
                : errorMsg.toString());
    }

    /**
     * 命令行执行结果类
     * CommandResult.code:0为正常,其他为错误
     * CommandResult.successMsg:执行结果的成功信息
     * CommandResult.errorMsg:执行结果的错误信息
     */
    public static class CommandResult {
        /**
         * 执行结果的状态值
         **/
        private int code;
        /**
         * 执行结果的成功信息
         **/
        private String successMsg;
        /**
         * 执行结果的错误信息
         **/
        private String errorMsg;

        public CommandResult(int code) {
            this.code = code;
        }

        public CommandResult(int code, String successMsg, String errorMsg) {
            this.code = code;
            this.successMsg = successMsg;
            this.errorMsg = errorMsg;
        }

        public int getCode() {
            return this.code;
        }

        public String getSuccessMsg() {
            return this.successMsg;
        }

        public String getErrorMsg() {
            return this.errorMsg;
        }
    }
}

 

package com.wanma.framework_api.helper;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;

/**
 * Windows命令行工具 助手类
 */
@Slf4j
public class CmdWinHelper {
    /**
     * 启动进程
     */
    public static void startProc(String processName) {
        log.info("启动应用程序:" + processName);
        if (StrUtil.isEmpty(processName)) {
            return;
        }
        try {
            Desktop.getDesktop().open(new File(processName));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("应用程序:" + processName + "不存在!");
        }
    }

    /**
     * 杀死进程
     */
    public static void killProc(String processName) {
        log.info("关闭应用程序:" + processName);
        if (StrUtil.isEmpty(processName)) {
            return;
        }
        try {
            executeCmd("taskkill /F /IM " + processName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行cmd命令
     */
    public static String executeCmd(String command) {
        log.info("Execute command : " + command);
        try {
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec("cmd /c " + command);
            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), CharsetUtil.CHARSET_UTF_8));
            String line = null;
            StringBuilder build = new StringBuilder();
            while ((line = br.readLine()) != null) {
                log.info(line);
                build.append(line);
            }
            return build.toString();
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 判断进程是否开启
     */
    public static boolean findProcess(String processName) {
        BufferedReader bufferedReader = null;
        try {
            Process proc = Runtime.getRuntime().exec("tasklist -fi " + '"' + "imagename eq " + processName + '"');
            bufferedReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                if (line.contains(processName)) {
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}