diff --git a/src/main/java/net/geedge/api/config/AdbShellProxyHandler.java b/src/main/java/net/geedge/api/config/AdbShellProxyHandler.java index 489b971..dcaabe6 100644 --- a/src/main/java/net/geedge/api/config/AdbShellProxyHandler.java +++ b/src/main/java/net/geedge/api/config/AdbShellProxyHandler.java @@ -5,6 +5,7 @@ import com.pty4j.PtyProcessBuilder; import net.geedge.api.entity.EnvApiYml; import net.geedge.api.util.AdbCommandBuilder; import net.geedge.api.util.AdbUtil; +import net.geedge.api.util.CommandExec; import net.geedge.common.T; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; @@ -40,7 +41,7 @@ public class AdbShellProxyHandler extends TextWebSocketHandler { super.afterConnectionEstablished(session); List cmd = AdbCommandBuilder.builder() - .serial(AdbUtil.getInstance(adb).getSerial()) + .serial(AdbUtil.getInstance(adb, new CommandExec(null)).getSerial()) .buildShellCommand("shell") .build(); diff --git a/src/main/java/net/geedge/api/controller/APIController.java b/src/main/java/net/geedge/api/controller/APIController.java index 5df1bad..1ecc64f 100644 --- a/src/main/java/net/geedge/api/controller/APIController.java +++ b/src/main/java/net/geedge/api/controller/APIController.java @@ -7,6 +7,7 @@ import cn.hutool.log.Log; import jakarta.servlet.http.HttpServletResponse; import net.geedge.api.entity.EnvApiYml; import net.geedge.api.util.AdbUtil; +import net.geedge.api.util.CommandExec; import net.geedge.common.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -28,9 +29,12 @@ public class APIController { @Autowired public APIController(EnvApiYml envApiYml) { - this.adbUtil = AdbUtil.getInstance(envApiYml.getAdb()); + this.adbUtil = AdbUtil.getInstance(envApiYml.getAdb(), new CommandExec(null)); } + @Autowired + private EnvApiYml apiYml; + @GetMapping("/status") public R status() { return R.ok(adbUtil.status()); @@ -61,7 +65,7 @@ public class APIController { File tempFile = T.FileUtil.file(Constant.TEMP_PATH, fileName); try { - AdbUtil.CommandResult result = adbUtil.pull(filePath, tempFile.getAbsolutePath(), false); + AdbUtil.CommandResult result = adbUtil.pull(filePath, tempFile.getAbsolutePath()); if (0 != result.exitCode()) { throw new APIException(result.output()); } @@ -104,7 +108,7 @@ public class APIController { tempFile = T.FileUtil.file(Constant.TEMP_PATH, file.getOriginalFilename()); file.transferTo(tempFile); - AdbUtil.CommandResult result = adbUtil.install(tempFile.getAbsolutePath(), true, true, false); + AdbUtil.CommandResult result = adbUtil.install(tempFile.getAbsolutePath(), true, true); if (0 != result.exitCode()) { throw new APIException(result.output()); } @@ -115,7 +119,7 @@ public class APIController { } if (T.StrUtil.isNotEmpty(path)) { - AdbUtil.CommandResult result = adbUtil.install(path, true, true, false); + AdbUtil.CommandResult result = adbUtil.install(path, true, true); if (0 != result.exitCode()) { throw new APIException(result.output()); } @@ -140,7 +144,7 @@ public class APIController { @PostMapping("/pcap") public R startTcpdump(@RequestParam(required = false, defaultValue = "") String packageName) { - AdbUtil.CommandResult result = adbUtil.startTcpdump(packageName, false); + AdbUtil.CommandResult result = adbUtil.startTcpdump(packageName); if (0 != result.exitCode()) { throw new APIException("exec tcpdump error"); } @@ -151,7 +155,7 @@ public class APIController { public synchronized void stopTcpdump(@RequestParam String id, @RequestParam(required = false, defaultValue = "false") Boolean returnFile, HttpServletResponse response) throws IOException { - AdbUtil.CommandResult result = adbUtil.stopTcpdump(id, false); + AdbUtil.CommandResult result = adbUtil.stopTcpdump(id); if (0 != result.exitCode()) { throw new APIException(result.output()); } @@ -165,7 +169,7 @@ public class APIController { if (T.StrUtil.isEmpty(filePath)) { throw new APIException(RCode.NOT_EXISTS); } - AdbUtil.CommandResult pulled = adbUtil.pull(filePath, tempFile.getAbsolutePath(), false); + AdbUtil.CommandResult pulled = adbUtil.pull(filePath, tempFile.getAbsolutePath()); if (0 != pulled.exitCode()) { throw new APIException(pulled.output()); } @@ -180,7 +184,7 @@ public class APIController { } finally { if (T.StrUtil.isNotEmpty(filePath)) { // remove pcap file - adbUtil.execShellCommand(String.format("shell rm -rf %s", filePath), false); + adbUtil.execShellCommand(String.format("shell rm -rf %s", filePath)); } } } @@ -302,7 +306,7 @@ public class APIController { } finally { T.FileUtil.del(destination); } - PlaybookRunnable playbookRunnable = new PlaybookRunnable(adbUtil, apkFile, playbookAirDir, id, packageName); + PlaybookRunnable playbookRunnable = new PlaybookRunnable(apiYml, apkFile, playbookAirDir, id, packageName); ThreadUtil.execAsync(playbookRunnable); return R.ok(); } @@ -349,7 +353,7 @@ public class APIController { } // job dir File jobResult = T.FileUtil.file(Constant.TEMP_PATH, id); - File zipFile = T.FileUtil.file(Constant.TEMP_PATH, T.StrUtil.concat(true, id, ".zip")); + File zipFile = T.FileUtil.file(Constant.TEMP_PATH, id, T.StrUtil.concat(true, id, ".zip")); File[] files = jobResult.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { @@ -364,13 +368,14 @@ public class APIController { public class PlaybookRunnable extends Thread { private AdbUtil adbUtil; + private EnvApiYml envApiYml; private String tid; private File apkFile; private String packageName; private File playbookDir; - public PlaybookRunnable(AdbUtil adbUtil, File apkFile, File playbookDir, String tid, String packageName) { - this.adbUtil = adbUtil; + public PlaybookRunnable(EnvApiYml envApiYml, File apkFile, File playbookDir, String tid, String packageName) { + this.envApiYml = envApiYml; this.tid = tid; this.apkFile = apkFile; this.packageName = packageName; @@ -382,42 +387,40 @@ public class APIController { File logFile = FileUtil.file(Constant.TEMP_PATH, tid, "result.log"); try { - adbUtil.setLogFile(logFile); + T.FileUtil.appendString(String.format("Running with %s:%s Android Simulator \n", envApiYml.getAdb().getHost(), envApiYml.getAdb().getPort()), logFile, "UTF-8"); + adbUtil = new AdbUtil(envApiYml.getAdb(), new CommandExec(logFile)); Map resultMap = T.MapUtil.builder() .put("status", "running") .build(); Constant.PLAYBOOK_RUN_RESULT.put(tid, resultMap); - T.FileUtil.appendString(String.format("Running with %s Android Simulator \n", adbUtil.getSerial()), logFile, "UTF-8"); - // 1. install apk - AdbUtil.CommandResult install = adbUtil.install(apkFile.getAbsolutePath(), true, true, true); + AdbUtil.CommandResult install = adbUtil.install(apkFile.getAbsolutePath(), true, true); if (0 != install.exitCode()) { T.FileUtil.appendString(String.format("ERROR: Install apk failed: exit code %s \n", install.exitCode()), logFile, "UTF-8"); throw new APIException(install.output()); } // 2. star tcpdump - AdbUtil.CommandResult startTcpdump = adbUtil.startTcpdump(packageName, true); + AdbUtil.CommandResult startTcpdump = adbUtil.startTcpdump(packageName); if (0 != startTcpdump.exitCode()) { T.FileUtil.appendString(String.format("ERROR: Start tcpdump failed: exit code %s \n", startTcpdump.exitCode()), logFile, "UTF-8"); throw new APIException("exec tcpdump error"); } // 3. exec playbook - AdbUtil.CommandResult execResult = adbUtil.execPlaybook(playbookDir.getPath(), true); + AdbUtil.CommandResult execResult = adbUtil.execPlaybook(playbookDir.getPath(), logFile); if (0 != execResult.exitCode()) { // exec playbook error, stop tcpdump and delete pcap T.FileUtil.appendString(String.format("ERROR: Exec playbook failed: exit code %s \n", execResult.exitCode()), logFile, "UTF-8"); - AdbUtil.CommandResult stopTcpdump = adbUtil.stopTcpdump(startTcpdump.output(), true); - adbUtil.execShellCommand(String.format("shell rm -rf %s", stopTcpdump.output()), true); + AdbUtil.CommandResult stopTcpdump = adbUtil.stopTcpdump(startTcpdump.output()); + adbUtil.execShellCommand(String.format("shell rm -rf %s", stopTcpdump.output())); throw new APIException("exec playbook error"); } // 4. stop tcpdump - AdbUtil.CommandResult stopTcpdump = adbUtil.stopTcpdump(startTcpdump.output(), true); - T.FileUtil.appendString(T.StrUtil.concat(true, stopTcpdump.output(), "\n"), logFile, "UTF-8"); + AdbUtil.CommandResult stopTcpdump = adbUtil.stopTcpdump(startTcpdump.output()); if (0 != stopTcpdump.exitCode()) { T.FileUtil.appendString(String.format("ERROR: Stop tcpdump failed: exit code %s \n", stopTcpdump.exitCode()), logFile, "UTF-8"); throw new APIException(stopTcpdump.output()); @@ -430,15 +433,14 @@ public class APIController { throw new APIException(RCode.NOT_EXISTS); } - AdbUtil.CommandResult pull = adbUtil.pull(filePath, localPcapFile.getAbsolutePath(), true); - T.FileUtil.appendString(T.StrUtil.concat(true, pull.output(), "\n"), logFile, "UTF-8"); + AdbUtil.CommandResult pull = adbUtil.pull(filePath, localPcapFile.getAbsolutePath()); if (0 != pull.exitCode()) { T.FileUtil.appendString(String.format("ERROR: Pull pcap file failed: exit code %s \n", pull.exitCode()), logFile, "UTF-8"); throw new APIException(pull.output()); } // 6. delete android pcap - adbUtil.execShellCommand(String.format("shell rm -rf %s", filePath), true); + adbUtil.execShellCommand(String.format("shell rm -rf %s", filePath)); resultMap = T.MapUtil.builder() .put("status", "done") @@ -451,7 +453,7 @@ public class APIController { .build(); Constant.PLAYBOOK_RUN_RESULT.put(tid, resultMap); } finally { - adbUtil.stopApp(packageName, true); + adbUtil.stopApp(packageName); T.FileUtil.appendString(String.format("Job succeeded"), logFile, "UTF-8"); } } diff --git a/src/main/java/net/geedge/api/util/AdbUtil.java b/src/main/java/net/geedge/api/util/AdbUtil.java index 7cb0d20..c519a9a 100644 --- a/src/main/java/net/geedge/api/util/AdbUtil.java +++ b/src/main/java/net/geedge/api/util/AdbUtil.java @@ -32,14 +32,11 @@ public class AdbUtil { private Integer port; private Integer vncPort; - - private File logFile; + + private CommandExec commandExec; private ExecutorService threadPool; - public void setLogFile(File logFile) { - this.logFile = logFile; - } public String getSerial() { return T.StrUtil.isNotEmpty(this.serial) ? serial : String.format("%s:%s", this.host, this.port); @@ -48,11 +45,12 @@ public class AdbUtil { public record CommandResult(Integer exitCode, String output) { } - private AdbUtil(EnvApiYml.Adb adb) { + public AdbUtil(EnvApiYml.Adb adb, CommandExec commandExec) { this.serial = T.StrUtil.emptyToDefault(adb.getSerial(), ""); this.host = adb.getHost(); this.port = adb.getPort(); this.vncPort = adb.getVncPort(); + this.commandExec = commandExec; // adb connect if (!this.connect()) { log.error("[connect error, program exit]"); @@ -69,11 +67,11 @@ public class AdbUtil { return instance; } - public static AdbUtil getInstance(EnvApiYml.Adb connInfo) { + public static AdbUtil getInstance(EnvApiYml.Adb connInfo, CommandExec commandExec) { if (instance == null) { synchronized (AdbUtil.class) { if (instance == null) { - instance = new AdbUtil(connInfo); + instance = new AdbUtil(connInfo, commandExec); } } } @@ -93,7 +91,7 @@ public class AdbUtil { } } else { // remote - String result = new CommandExec(logFile ,false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .buildConnectCommand(this.host, this.port) .build()); log.info("[connect] [result: {}]", result); @@ -111,7 +109,7 @@ public class AdbUtil { */ public void init(boolean install) { // adb root - String result = new CommandExec(logFile ,false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildRootCommand() .build() @@ -120,26 +118,26 @@ public class AdbUtil { if (install) { // install droidVNC NG - CommandResult installed = this.install(DEFAULT_DROIDVNC_NG_APK_PATH, true, true,false); + CommandResult installed = this.install(DEFAULT_DROIDVNC_NG_APK_PATH, true, true); log.info("[init] [install droidVNC NG] [result: {}]", installed); // 上传默认配置 - this.execShellCommand("shell mkdir -p /storage/emulated/0/Android/data/net.christianbeier.droidvnc_ng/files",false); + this.execShellCommand("shell mkdir -p /storage/emulated/0/Android/data/net.christianbeier.droidvnc_ng/files"); this.push(DEFAULT_DROIDVNC_NG_DEFAULTS_JSON_PATH, "/storage/emulated/0/Android/data/net.christianbeier.droidvnc_ng/files/defaults.json"); // 无障碍权限 - this.execShellCommand("shell settings put secure enabled_accessibility_services net.christianbeier.droidvnc_ng/.InputService:$(settings get secure enabled_accessibility_services)",false); + this.execShellCommand("shell settings put secure enabled_accessibility_services net.christianbeier.droidvnc_ng/.InputService:$(settings get secure enabled_accessibility_services)"); // 存储空间权限 - this.execShellCommand("shell pm grant net.christianbeier.droidvnc_ng android.permission.WRITE_EXTERNAL_STORAGE",false); + this.execShellCommand("shell pm grant net.christianbeier.droidvnc_ng android.permission.WRITE_EXTERNAL_STORAGE"); // 屏幕录制权限 - this.execShellCommand("shell appops set net.christianbeier.droidvnc_ng PROJECT_MEDIA allow",false); + this.execShellCommand("shell appops set net.christianbeier.droidvnc_ng PROJECT_MEDIA allow"); // ACTION_STOP - this.execShellCommand("shell am start-foreground-service -n net.christianbeier.droidvnc_ng/.MainService -a net.christianbeier.droidvnc_ng.ACTION_STOP --es net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY d042e2b5d5f348588a4e1a243eb7a9a0",false); + this.execShellCommand("shell am start-foreground-service -n net.christianbeier.droidvnc_ng/.MainService -a net.christianbeier.droidvnc_ng.ACTION_STOP --es net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY d042e2b5d5f348588a4e1a243eb7a9a0"); } // ACTION_START - this.execShellCommand("shell am start-foreground-service -n net.christianbeier.droidvnc_ng/.MainService -a net.christianbeier.droidvnc_ng.ACTION_START --es net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY d042e2b5d5f348588a4e1a243eb7a9a0",false); + this.execShellCommand("shell am start-foreground-service -n net.christianbeier.droidvnc_ng/.MainService -a net.christianbeier.droidvnc_ng.ACTION_START --es net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY d042e2b5d5f348588a4e1a243eb7a9a0"); // 添加自定义链 this.addAswOutputChain(); @@ -179,7 +177,7 @@ public class AdbUtil { m.put("type", type); // check root - String checkRootResult = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String checkRootResult = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildCheckRootCommand() .build() @@ -195,7 +193,7 @@ public class AdbUtil { * @return */ private AdbDevice getAdbDevice() { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .buildDevicesCommand() .build() ); @@ -220,7 +218,7 @@ public class AdbUtil { * @return */ private Map getProp() { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildGetpropCommand() .build() @@ -237,7 +235,7 @@ public class AdbUtil { } // 分辨率 Physical size: 1440x3040 - String wmSize = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String wmSize = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildWmSizeCommand() .build() @@ -251,7 +249,7 @@ public class AdbUtil { * md5sum */ private CommandResult md5sum(String path) { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildMd5sumCommand(path) .build() @@ -269,7 +267,7 @@ public class AdbUtil { * 0 success; !0 failed */ public CommandResult push(String local, String remote) { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildPushCommand(local, remote) .build() @@ -282,8 +280,8 @@ public class AdbUtil { * pull * 0 success; !0 failed */ - public CommandResult pull(String remote, String local, boolean isRecordLog) { - String result = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + public CommandResult pull(String remote, String local) { + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildPullCommand(remote, local) .build() @@ -298,7 +296,7 @@ public class AdbUtil { * stat filename */ public List listDir(String path) { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildLsDirCommand(path) .build() @@ -336,7 +334,7 @@ public class AdbUtil { String statCommand = "shell stat -c \"'%N %A %g %u %s %a %X %Y'\" " + statFilePath; futureList.add( CompletableFuture.supplyAsync(() -> { - String statResult = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String statResult = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(statCommand.replaceAll("\\\\", "/")) .build() @@ -397,7 +395,7 @@ public class AdbUtil { * @return */ public List listApp(String arg) { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildPmListPackagesCommand(arg) .build() @@ -413,7 +411,7 @@ public class AdbUtil { String packageName = T.StrUtil.trim(line.substring(prefix.length())); if (T.StrUtil.equals(DEFAULT_DROIDVNC_NG_PKG_NAME, packageName)) continue; - String dumpsysResult = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String dumpsysResult = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand("shell dumpsys package " + packageName) .build() @@ -437,7 +435,7 @@ public class AdbUtil { String md5Value = md5sumRes.output(); File localApk = T.FileUtil.file(Constant.TEMP_PATH, md5Value + ".apk"); if (!T.FileUtil.exist(localApk)) { - CommandResult pulled = this.pull(finalApkPath, localApk.getAbsolutePath(), false); + CommandResult pulled = this.pull(finalApkPath, localApk.getAbsolutePath()); if (0 != pulled.exitCode()) { log.warn("[listApp] [pull apk error] [pkg: {}]", packageName); return null; @@ -494,8 +492,8 @@ public class AdbUtil { * install app * adb install apk */ - public CommandResult install(String localFilePath, boolean isDebugApk, boolean isReInstall, boolean isRecordLog) { - String result = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + public CommandResult install(String localFilePath, boolean isDebugApk, boolean isReInstall) { + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildInstallCommand(localFilePath, isDebugApk, isReInstall) .build()); @@ -509,7 +507,7 @@ public class AdbUtil { * adb uninstall package_name */ public CommandResult uninstall(String packageName) { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildUnInstallCommand(packageName) .build() @@ -522,8 +520,8 @@ public class AdbUtil { * stop app * adb shell am force-stop package_name */ - public CommandResult stopApp(String packageName, boolean isRecordLog) { - String result = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + public CommandResult stopApp(String packageName) { + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildStopAppCommand(packageName) .build() @@ -539,13 +537,13 @@ public class AdbUtil { @Deprecated private void cleanIptables() { // Delete all rules in chain or all chains - new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand("shell iptables -F") .build() ); // Delete user-defined chain - new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand("shell iptables -X") .build() @@ -556,7 +554,7 @@ public class AdbUtil { * list tcpdump */ public List listTcpdump() { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell \"ps -ef | grep tcpdump | grep -v grep | grep capture_ | awk '{print $NF}' \"")) .build()); @@ -591,11 +589,11 @@ public class AdbUtil { * start Tcpdump * tcpdump pcap */ - public CommandResult startTcpdump(String packageName, boolean isRecordLog) { + public CommandResult startTcpdump(String packageName) { String taskId = T.IdUtil.fastSimpleUUID(); if (T.StrUtil.isNotEmpty(packageName)) { log.info("[startTcpdump] [capture app package] [pkg: {}]", packageName); - String dumpsysResult = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + String dumpsysResult = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand("shell dumpsys package " + packageName) .build() @@ -607,20 +605,20 @@ public class AdbUtil { .map(s -> T.StrUtil.trim(s).replaceAll("userId=", "")) .orElseThrow(() -> new APIException("Not found userId by package name. package name: " + packageName)); - new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell iptables -A OUTPUT -m owner --uid-owner %s -j CONNMARK --set-mark %s", userId, userId)) .build()); - new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell iptables -A INPUT -m connmark --mark %s -j NFLOG --nflog-group %s", userId, userId)) .build()); - new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell iptables -A OUTPUT -m connmark --mark %s -j NFLOG --nflog-group %s", userId, userId)) .build()); - String ruleList = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + String ruleList = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand("shell iptables -L") .build()); @@ -628,7 +626,7 @@ public class AdbUtil { // pcap 格式:capture_{userId}_{pcakageName}_{taskId}.pcap String pcapFilePath = "/data/local/tmp/capture_" + userId + "_" + packageName + "_" + taskId + ".pcap"; - new CommandExec(logFile, isRecordLog).execForProcess(AdbCommandBuilder.builder() + commandExec.execForProcess(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell tcpdump -i nflog:%s -w %s &", userId, pcapFilePath)) .build()); @@ -636,13 +634,13 @@ public class AdbUtil { log.info("[startTcpdump] [capture all package]"); // pcap 格式:capture_all_{taskId}.pcap String pcapFilePath = "/data/local/tmp/capture_all_" + taskId + ".pcap"; - new CommandExec(logFile, isRecordLog).execForProcess(AdbCommandBuilder.builder() + commandExec.execForProcess(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell tcpdump not port %s -w %s &", this.vncPort, pcapFilePath)) .build()); } - String result = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell \"ps -ef | grep tcpdump | grep -v grep | grep %s | awk '{print $2}' \"", taskId)) .build()); @@ -654,8 +652,8 @@ public class AdbUtil { * stop tcpdump * kill -INT {pid} */ - public CommandResult stopTcpdump(String id, boolean isRecordLog) { - String pcapFilePath = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + public CommandResult stopTcpdump(String id) { + String pcapFilePath = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell \"ps -ef | grep tcpdump | grep -v grep | grep %s | awk '{print $NF}' \"", id)) .build()); @@ -665,21 +663,21 @@ public class AdbUtil { String[] split = T.FileUtil.mainName(pcapFilePath).split("_"); String userId = split[1]; log.info("[stopTcpdump] [remove iptables rule] [userId: {}]", userId); - new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell iptables -D OUTPUT -m owner --uid-owner %s -j CONNMARK --set-mark %s", userId, userId)) .build()); - new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell iptables -D INPUT -m connmark --mark %s -j NFLOG --nflog-group %s", userId, userId)) .build()); - new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell iptables -D OUTPUT -m connmark --mark %s -j NFLOG --nflog-group %s", userId, userId)) .build()); } } - String result = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell \"ps -ef | grep tcpdump | grep -v grep | grep %s | awk '{print $2}' | xargs kill -INT \"", id)) .build()); @@ -688,7 +686,7 @@ public class AdbUtil { for (int i = 0; i < 10; i++) { T.ThreadUtil.sleep(500); - String str = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + String str = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell \"ps -ef | grep tcpdump | grep -v grep | grep %s \"", id)) .build()); @@ -708,8 +706,8 @@ public class AdbUtil { /** * exec shell command */ - public void execShellCommand(String shellCmd, boolean isRecordLog) { - String result = new CommandExec(logFile, isRecordLog).exec(AdbCommandBuilder.builder() + public void execShellCommand(String shellCmd) { + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(shellCmd) .build()); @@ -720,7 +718,7 @@ public class AdbUtil { * exec shell command */ public String execShellCommand(String cmd, Integer timeout){ - Process process = new CommandExec(logFile, false).execForProcess(AdbCommandBuilder.builder() + Process process = commandExec.execForProcess(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand("shell " + cmd) .build()); @@ -746,16 +744,16 @@ public class AdbUtil { */ private void addAswOutputChain() { // name=ASW_OUTPUT - this.execShellCommand("shell iptables -N ASW_OUTPUT", false); + this.execShellCommand("shell iptables -N ASW_OUTPUT"); - String outputChainResult = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String outputChainResult = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildShellCommand(String.format("shell \"iptables -L OUTPUT --line-numbers | grep ASW_OUTPUT\"")) .build()); log.info("[addAswOutputChain] [ASW_OUTPUT in OUTPUT Chain] [result: {}]", outputChainResult); if (T.StrUtil.isEmpty(outputChainResult)) { // ASW_OUTPUT 添加到 OUTPUT 链中 - this.execShellCommand("shell iptables -A OUTPUT -j ASW_OUTPUT", false); + this.execShellCommand("shell iptables -A OUTPUT -j ASW_OUTPUT"); } } @@ -764,7 +762,7 @@ public class AdbUtil { * iptables -nL ASW_OUTPUT --line-numbers */ public List listAcl() { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildIptablesLnRulesCommand("ASW_OUTPUT") .build()); @@ -811,7 +809,7 @@ public class AdbUtil { this.addAswOutputChain(); // add chain ruls - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildIptablesAddRuleCommand("ASW_OUTPUT", protocol, ip, port) .build()); @@ -825,7 +823,7 @@ public class AdbUtil { */ public void deleteAcl(String protocol, String ip, String port) { // add chain ruls - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildIptablesDelRuleCommand("ASW_OUTPUT", protocol, ip, port) .build()); @@ -837,7 +835,7 @@ public class AdbUtil { * iptables -F ASW_OUTPUT */ public CommandResult flushAcl() { - String result = new CommandExec(logFile, false).exec(AdbCommandBuilder.builder() + String result = commandExec.exec(AdbCommandBuilder.builder() .serial(this.getSerial()) .buildIptablesFlushRuleCommand("ASW_OUTPUT") .build()); @@ -859,47 +857,21 @@ public class AdbUtil { } - class CommandExec { - - private File logFile; - private boolean isRecordLog; - - public String exec(List command) { - String str = T.RuntimeUtil.execForStr(T.CharsetUtil.CHARSET_UTF_8, command.stream().toArray(String[]::new)); - if (isRecordLog) { - T.FileUtil.appendString(T.StrUtil.concat(true, "$ ", command.stream().collect(Collectors.joining(" ")), "\n"), this.logFile, "UTF-8"); - T.FileUtil.appendString(T.StrUtil.concat(true, str.stripTrailing(), "\n"), this.logFile, "UTF-8"); - } - return str.stripTrailing(); - } - - public Process execForProcess(List command) { - Process process = T.RuntimeUtil.exec(command.stream().toArray(String[]::new)); - return process; - } - - public CommandExec(File logFile, boolean isRecordLog) { - this.logFile = logFile; - this.isRecordLog = isRecordLog; - } - } - - public CommandResult execPlaybook(String playbookPath, boolean isRecordLog) { + public CommandResult execPlaybook(String playbookPath, File logFile) { log.info("[execPlaybook] [begin!] [serial:{}]", this.getSerial()); List command = new AdbCommandBuilder("airtest") .buildRunPlaybook(playbookPath, this.getSerial()) .build(); - Process process = new CommandExec(logFile, isRecordLog).execForProcess(command); + Process process = commandExec.execForProcess(command); ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(() -> T.IoUtil.read(process.getInputStream(), T.CharsetUtil.CHARSET_UTF_8)); try { int exitCode = process.waitFor(); String result = future.get(10, TimeUnit.SECONDS); - if (isRecordLog){ - T.FileUtil.appendString(T.StrUtil.concat(true, "$ ", command.stream().collect(Collectors.joining(" ")), "\n"), this.logFile, "UTF-8"); - T.FileUtil.appendString(T.StrUtil.concat(true, result.stripTrailing(), "\n"), this.logFile, "UTF-8"); - } + T.FileUtil.appendString(T.StrUtil.concat(true, "$ ", command.stream().collect(Collectors.joining(" ")), "\n"), logFile, "UTF-8"); + T.FileUtil.appendString(T.StrUtil.concat(true, result.stripTrailing(), "\n"), logFile, "UTF-8"); + return new CommandResult(exitCode, result); } catch (Exception e) { process.destroyForcibly(); diff --git a/src/main/java/net/geedge/api/util/CommandExec.java b/src/main/java/net/geedge/api/util/CommandExec.java new file mode 100644 index 0000000..cab80f4 --- /dev/null +++ b/src/main/java/net/geedge/api/util/CommandExec.java @@ -0,0 +1,30 @@ +package net.geedge.api.util; + +import net.geedge.common.T; + +import java.io.File; +import java.util.List; +import java.util.stream.Collectors; + +public class CommandExec { + + private File logFile; + + public String exec(List command) { + String str = T.RuntimeUtil.execForStr(T.CharsetUtil.CHARSET_UTF_8, command.stream().toArray(String[]::new)); + if (logFile != null) { + T.FileUtil.appendString(T.StrUtil.concat(true, "$ ", command.stream().collect(Collectors.joining(" ")), "\n"), this.logFile, "UTF-8"); + T.FileUtil.appendString(T.StrUtil.concat(true, str.stripTrailing(), "\n"), this.logFile, "UTF-8"); + } + return str.stripTrailing(); + } + + public Process execForProcess(List command) { + Process process = T.RuntimeUtil.exec(command.stream().toArray(String[]::new)); + return process; + } + + public CommandExec(File logFile ) { + this.logFile = logFile; + } + } \ No newline at end of file