diff --git a/bin/as.sh b/bin/as.sh index 9c70e3755..7974e2701 100755 --- a/bin/as.sh +++ b/bin/as.sh @@ -120,6 +120,9 @@ HEIGHT= # arthas-client terminal width WIDTH= +# select target process by classname or JARfilename +SELECT= + # Verbose, print debug info. VERBOSE=false @@ -423,6 +426,7 @@ Options and Arguments: --debug-attach Debug attach agent --tunnel-server Remote tunnel server url --agent-id Special agent id + --select select target process by classname or JARfilename -c,--command Command to execute, multiple commands separated by ; -f,--batch-file The batch file to execute @@ -443,6 +447,7 @@ EXAMPLES: ./as.sh --use-version 3.2.0 ./as.sh --session-timeout 3600 ./as.sh --attach-only + ./as.sh --select arthas-demo ./as.sh --repo-mirror aliyun --use-http WIKI: https://alibaba.github.io/arthas @@ -583,6 +588,11 @@ parse_arguments() shift # past argument shift # past value ;; + --select) + SELECT="$2" + shift # past argument + shift # past value + ;; -v|--verbose) VERBOSE=true shift # past argument @@ -634,6 +644,15 @@ parse_arguments() fi fi + # try to find target pid by --select option + if [ -z ${TARGET_PID} ] && [ ${SELECT} ]; then + local IFS=$'\n' + CANDIDATES=($(call_jps | grep -v sun.tools.jps.Jps | grep "${SELECT}" | awk '{print $0}')) + if [ ${#CANDIDATES[@]} -eq 1 ]; then + TARGET_PID=${CANDIDATES[0]} + fi + fi + # check pid if [ -z ${TARGET_PID} ] && [ ${BATCH_MODE} = false ]; then # interactive mode diff --git a/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java b/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java index a447ac150..77c1ed04e 100644 --- a/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java +++ b/boot/src/main/java/com/taobao/arthas/boot/Bootstrap.java @@ -49,6 +49,7 @@ import com.taobao.middleware.cli.annotations.Summary; + " java -jar arthas-boot.jar -f batch.as \n" + " java -jar arthas-boot.jar --use-version 3.2.0\n" + " java -jar arthas-boot.jar --versions\n" + + " java -jar arthas-boot.jar --select arthas-demo\n" + " java -jar arthas-boot.jar --session-timeout 3600\n" + " java -jar arthas-boot.jar --attach-only\n" + " java -jar arthas-boot.jar --repo-mirror aliyun --use-http\n" + "WIKI:\n" + " https://alibaba.github.io/arthas\n") @@ -114,7 +115,9 @@ public class Bootstrap { private String statUrl; - static { + private String select; + + static { ARTHAS_LIB_DIR = new File( System.getProperty("user.home") + File.separator + ".arthas" + File.separator + "lib"); try { @@ -256,6 +259,12 @@ public class Bootstrap { this.statUrl = statUrl; } + @Option(longName = "select") + @Description("select target process by classname or JARfilename") + public void setSelect(String select) { + this.select = select; + } + public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { @@ -333,7 +342,7 @@ public class Bootstrap { // select pid if (pid < 0) { try { - pid = ProcessUtils.select(bootstrap.isVerbose(), telnetPortPid); + pid = ProcessUtils.select(bootstrap.isVerbose(), telnetPortPid, bootstrap.getSelect()); } catch (InputMismatchException e) { System.out.println("Please input an integer to select pid."); System.exit(1); @@ -690,4 +699,8 @@ public class Bootstrap { public String getStatUrl() { return statUrl; } + + public String getSelect() { + return select; + } } diff --git a/boot/src/main/java/com/taobao/arthas/boot/ProcessUtils.java b/boot/src/main/java/com/taobao/arthas/boot/ProcessUtils.java index 592ba7181..cd52a9897 100644 --- a/boot/src/main/java/com/taobao/arthas/boot/ProcessUtils.java +++ b/boot/src/main/java/com/taobao/arthas/boot/ProcessUtils.java @@ -10,6 +10,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Scanner; import java.util.InputMismatchException; @@ -28,7 +29,7 @@ public class ProcessUtils { private static String FOUND_JAVA_HOME = null; @SuppressWarnings("resource") - public static long select(boolean v, long telnetPortPid) throws InputMismatchException { + public static long select(boolean v, long telnetPortPid, String select) throws InputMismatchException { Map processMap = listProcessByJps(v); // Put the port that is already listening at the first if (telnetPortPid > 0 && processMap.containsKey(telnetPortPid)) { @@ -45,6 +46,28 @@ public class ProcessUtils { return -1; } + // select target process by the '--select' option when match only one process + if (select != null && !select.trim().isEmpty()) { + int matchedSelectCount = 0; + Long matchedPid = null; + for (Entry entry : processMap.entrySet()) { + if (entry.getValue().contains(select)) { + matchedSelectCount++; + matchedPid = entry.getKey(); + } + } + if (matchedSelectCount == 1) { + return matchedPid; + } + } + + if (processMap.size() == 1) { + Entry entry = processMap.entrySet().iterator().next(); + if (entry.getValue().contains(select)) { + return entry.getKey(); + } + } + AnsiLog.info("Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER."); // print list int count = 1;