From c3d2f1da6bd8c04d950b650c6935aaea44248707 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Tue, 9 Oct 2018 11:33:08 +0800 Subject: [PATCH 1/6] clean as.sh --- bin/as.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/bin/as.sh b/bin/as.sh index a7b2e7a5bac..7d20ae13baa 100755 --- a/bin/as.sh +++ b/bin/as.sh @@ -143,13 +143,6 @@ get_remote_version() curl -sLk --connect-timeout ${SO_TIMEOUT} "${ARTHAS_REMOTE_VERSION_URL}" | sed 's/{.*latestVersion":"*\([0-9a-zA-Z\\.\\-]*\)"*,*.*}/\1/' } -# make version format to comparable format like 000.000.(0){15} -# $1 : version -to_comparable_version() -{ - echo ${1}|awk -F "." '{printf("%d.%d.%d\n",$1,$2,$3)}' -} - # update arthas if necessary update_if_necessary() { From e2ac4673e7ec8d24f28406ce2ca5dffd3187eba7 Mon Sep 17 00:00:00 2001 From: beiwei30 Date: Wed, 10 Oct 2018 13:42:58 +0800 Subject: [PATCH 2/6] enhance translation for advice-class --- site/src/site/sphinx/en/advice-class.md | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/site/src/site/sphinx/en/advice-class.md b/site/src/site/sphinx/en/advice-class.md index 479f9305589..d047105727b 100644 --- a/site/src/site/sphinx/en/advice-class.md +++ b/site/src/site/sphinx/en/advice-class.md @@ -1,4 +1,4 @@ -Critical Fields in Expressions +Fundamental Fields in Expressions ============================== There is a very fundamental class `Advice` for the expressions used in filtering, tracing or monitoring and other aspects in commands. @@ -16,29 +16,29 @@ public class Advice { private final boolean isBefore; private final boolean isThrow; private final boolean isReturn; - ... + // getter/setter } ``` +Description for the variables in the class `Advice`: + |Name|Specification| |---:|:---| -|loader|class loader of the class| -|clazz|the reference of the class| -|method|the reflective reference of the method| -|target|the instance of the class| -|params|the parameters of the method, which is an array (when there is no argument in the method, it will be an empty array)| -|returnObj|the return value of the method - only when `isReturn==true`, it's a valid result but if the return value is `void` then it will be a `null`| -|throwExp|the exceptions thrown by the method invoking - only when `isThrow==true`, it's a valid thrown exception| -|isBefore|assistant checking flag used in [`before-watching` point](watch.md) and at this very moment: `isBefore==true`, `isThrow==false` and `isReturn==false` since it's before we invoke the method| -|isThrow|assistant checking flag: whether the current method invoking ends with exceptions| -|isReturn|assistant checking flag: whether the method invoking exits normally without exceptions| - -F.Y.I -1. all the *fields* mentioned in the table above can be used directly in the `expressions`; -2. if the expressions are [invalid OGNL](https://en.wikipedia.org/wiki/OGNL), the command will be cancelled automatically with hints to correct the expressions; -3. [typical use cases](https://github.com/alibaba/arthas/issues/71); -4. [OGNL official usage guide](https://commons.apache.org/proper/commons-ognl/language-guide.html). +|loader|the class loader for the current called class| +|clazz|the reference to the current called class| +|method|the reference to the current called method| +|target|the instance of the current called class| +|params|the parameters for the current call, which is an array (when there's no parameter, it will be an empty array)| +|returnObj|the return value from the current call - only available when the method call returns normally (`isReturn==true`), and `null` is for `void` return value| +|throwExp|the exceptions thrown from the current call - only available when the method call throws exception (`isThrow==true`)| +|isBefore|flag to indicate the method is about to execute. `isBefore==true` but `isThrow==false` and `isReturn==false` since it's no way to know how the method call will end| +|isThrow|flag to indicate the method call ends with exception thrown| +|isReturn|flag to indicate the method call ends normally without exception thrown| + +All variables listed above can be used directly in the [OGNL expression](https://commons.apache.org/proper/commons-ognl/language-guide.html). The command will not execute and exit if there's illegal OGNL grammar or unexpected variable in the expression. +* [typical use cases](https://github.com/alibaba/arthas/issues/71); +* [OGNL language guide](https://commons.apache.org/proper/commons-ognl/language-guide.html). From f76e9e33af81ca33e15f3d218976e1711a32d684 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Wed, 10 Oct 2018 16:13:52 +0800 Subject: [PATCH 3/6] fix as.sh test string contains space problem. #180 --- bin/as.sh | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/bin/as.sh b/bin/as.sh index 7d20ae13baa..be4a49cf6b1 100755 --- a/bin/as.sh +++ b/bin/as.sh @@ -75,7 +75,7 @@ default() # check arthas permission check_permission() { - [ ! -w ${HOME} ] \ + [ ! -w "${HOME}" ] \ && exit_on_err 1 "permission denied, ${HOME} is not writable." } @@ -86,18 +86,18 @@ reset_for_env() { # init ARTHAS' lib - mkdir -p ${ARTHAS_LIB_DIR} \ + mkdir -p "${ARTHAS_LIB_DIR}" \ || exit_on_err 1 "create ${ARTHAS_LIB_DIR} fail." # if env define the JAVA_HOME, use it first # if is alibaba opts, use alibaba ops's default JAVA_HOME - [ -z ${JAVA_HOME} ] && JAVA_HOME=/opt/taobao/java + [ -z "${JAVA_HOME}" ] && JAVA_HOME=/opt/taobao/java # iterater throught candidates to find a proper JAVA_HOME at least contains tools.jar which is required by arthas. - if [ ! -d ${JAVA_HOME} ]; then + if [ ! -d "${JAVA_HOME}" ]; then JAVA_HOME_CANDIDATES=($(ps aux | grep java | grep -v 'grep java' | awk '{print $11}' | sed -n 's/\/bin\/java$//p')) for JAVA_HOME_TEMP in ${JAVA_HOME_CANDIDATES[@]}; do - if [ -f ${JAVA_HOME_TEMP}/lib/tools.jar ]; then + if [ -f "${JAVA_HOME_TEMP}/lib/tools.jar" ]; then JAVA_HOME=${JAVA_HOME_TEMP} break fi @@ -107,7 +107,7 @@ reset_for_env() # maybe 1.8.0_162 , 11-ea local JAVA_VERSION_STR=$(${JAVA_HOME}/bin/java -version 2>&1|awk -F '"' '$2>"1.5"{print $2}') # check the jvm version, we need 1.6+ - [[ ! -x ${JAVA_HOME} || -z ${JAVA_VERSION_STR} ]] && exit_on_err 1 "illegal ENV, please set \$JAVA_HOME to JDK6+" + [[ ! -x "${JAVA_HOME}" || -z "${JAVA_VERSION_STR}" ]] && exit_on_err 1 "illegal ENV, please set \$JAVA_HOME to JDK6+" local JAVA_VERSION if [[ $JAVA_VERSION_STR = "1."* ]]; then @@ -119,7 +119,7 @@ reset_for_env() # when java version greater than 9, there is no tools.jar if [[ "$JAVA_VERSION" -lt 9 ]];then # check tools.jar exists - if [ ! -f ${JAVA_HOME}/lib/tools.jar ]; then + if [ ! -f "${JAVA_HOME}/lib/tools.jar" ]; then exit_on_err 1 "${JAVA_HOME}/lib/tools.jar does not exist, arthas could not be launched!" else BOOT_CLASSPATH=-Xbootclasspath/a:${JAVA_HOME}/lib/tools.jar @@ -134,7 +134,7 @@ reset_for_env() # get latest version from local get_local_version() { - ls ${ARTHAS_LIB_DIR} | sort | tail -1 + ls "${ARTHAS_LIB_DIR}" | sort | tail -1 } # get latest version from remote @@ -148,17 +148,17 @@ update_if_necessary() { local update_version=$1 - if [ ! -d ${ARTHAS_LIB_DIR}/${update_version} ]; then + if [ ! -d "${ARTHAS_LIB_DIR}/${update_version}" ]; then echo "updating version ${update_version} ..." local temp_target_lib_dir="$TMP_DIR/temp_${update_version}_$$" local temp_target_lib_zip="${temp_target_lib_dir}/arthas-${update_version}-bin.zip" local target_lib_dir="${ARTHAS_LIB_DIR}/${update_version}/arthas" - mkdir -p ${target_lib_dir} + mkdir -p "${target_lib_dir}" # clean - rm -rf ${temp_target_lib_dir} - rm -rf ${target_lib_dir} + rm -rf "${temp_target_lib_dir}" + rm -rf "${target_lib_dir}" mkdir -p "${temp_target_lib_dir}" \ || exit_on_err 1 "create ${temp_target_lib_dir} fail." @@ -167,16 +167,16 @@ update_if_necessary() curl \ -#Lk \ --connect-timeout ${SO_TIMEOUT} \ - -o ${temp_target_lib_zip} \ + -o "${temp_target_lib_zip}" \ "${ARTHAS_REMOTE_DOWNLOAD_URL}/${update_version}/arthas-packaging-${update_version}-bin.zip" \ || return 1 # unzip arthas lib - unzip ${temp_target_lib_zip} -d ${temp_target_lib_dir} || (rm -rf ${temp_target_lib_dir} \ - ${ARTHAS_LIB_DIR}/${update_version} && return 1) + unzip "${temp_target_lib_zip}" -d "${temp_target_lib_dir}" || (rm -rf "${temp_target_lib_dir}" \ + "${ARTHAS_LIB_DIR}/${update_version}" && return 1) # rename - mv ${temp_target_lib_dir} ${target_lib_dir} || return 1 + mv "${temp_target_lib_dir}" "${target_lib_dir}" || return 1 # print success echo "update completed." @@ -221,7 +221,7 @@ $(${JAVA_HOME}/bin/jps -l | grep -v sun.tools.jps.Jps) list_versions() { echo "Arthas versions under ${ARTHAS_LIB_DIR}:" - ls -1 ${ARTHAS_LIB_DIR} + ls -1 "${ARTHAS_LIB_DIR}" } # parse the argument @@ -432,26 +432,26 @@ main() local remote_version=$(get_remote_version) - if [ -z ${ARTHAS_VERSION} ]; then - update_if_necessary ${remote_version} || echo "update fail, ignore this update." 1>&2 + if [ -z "${ARTHAS_VERSION}" ]; then + update_if_necessary "${remote_version}" || echo "update fail, ignore this update." 1>&2 else - update_if_necessary ${ARTHAS_VERSION} || echo "update fail, ignore this update." 1>&2 + update_if_necessary "${ARTHAS_VERSION}" || echo "update fail, ignore this update." 1>&2 fi local arthas_local_version=$(get_local_version) - if [ ! -z ${ARTHAS_VERSION} ]; then + if [ ! -z "${ARTHAS_VERSION}" ]; then arthas_local_version=${ARTHAS_VERSION} fi - if [ ! -d ${ARTHAS_LIB_DIR}/${arthas_local_version} ]; then + if [ ! -d "${ARTHAS_LIB_DIR}/${arthas_local_version}" ]; then exit_on_err 1 "arthas not found, please check your network." fi sanity_check echo "Calculating attach execution time..." - time (attach_jvm ${arthas_local_version} || exit 1) + time (attach_jvm "${arthas_local_version}" || exit 1) if [ $? -ne 0 ]; then exit_on_err 1 "attach to target jvm (${TARGET_PID}) failed, check ${HOME}/logs/arthas/arthas.log or stderr of target jvm for any exceptions." From 21640a27f733ca3cc5b82e0b9c14f1683c206484 Mon Sep 17 00:00:00 2001 From: Hearen Date: Wed, 10 Oct 2018 23:07:05 +0800 Subject: [PATCH 4/6] fix some typos in error prompts --- .../taobao/arthas/core/command/klass100/RedefineCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/taobao/arthas/core/command/klass100/RedefineCommand.java b/core/src/main/java/com/taobao/arthas/core/command/klass100/RedefineCommand.java index 0d9cd82097d..1edada2d6a8 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/klass100/RedefineCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/klass100/RedefineCommand.java @@ -64,12 +64,12 @@ public void process(CommandProcess process) { for (String path : paths) { File file = new File(path); if (!file.exists()) { - process.write("path is not exists, path:" + path + "\n"); + process.write("file does not exist, path:" + path + "\n"); process.end(); return; } if (!file.isFile()) { - process.write("path is not a normal file, path:" + path + "\n"); + process.write("not a normal file, path:" + path + "\n"); process.end(); return; } From 2ea00a33947084844f74eab5b1c515009347a8ca Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Thu, 11 Oct 2018 10:54:06 +0800 Subject: [PATCH 5/6] improve finding java version. #212 --- bin/as.sh | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/bin/as.sh b/bin/as.sh index be4a49cf6b1..d623fd181a6 100755 --- a/bin/as.sh +++ b/bin/as.sh @@ -105,16 +105,24 @@ reset_for_env() fi # maybe 1.8.0_162 , 11-ea - local JAVA_VERSION_STR=$(${JAVA_HOME}/bin/java -version 2>&1|awk -F '"' '$2>"1.5"{print $2}') - # check the jvm version, we need 1.6+ - [[ ! -x "${JAVA_HOME}" || -z "${JAVA_VERSION_STR}" ]] && exit_on_err 1 "illegal ENV, please set \$JAVA_HOME to JDK6+" - local JAVA_VERSION - if [[ $JAVA_VERSION_STR = "1."* ]]; then - JAVA_VERSION=$(echo $veJAVA_VERSION_STRr | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q') - else - JAVA_VERSION=$(echo $JAVA_VERSION_STR | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q') - fi + + local IFS=$'\n' + # remove \r for Cygwin + local lines=$(${JAVA_HOME}/bin/java -version 2>&1 | tr '\r' '\n') + for line in $lines; do + if [[ (-z $JAVA_VERSION) && ($line = *"version \""*) ]] + then + local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q') + # on macOS, sed doesn't support '?' + if [[ $ver = "1."* ]] + then + JAVA_VERSION=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q') + else + JAVA_VERSION=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q') + fi + fi + done # when java version greater than 9, there is no tools.jar if [[ "$JAVA_VERSION" -lt 9 ]];then @@ -365,8 +373,8 @@ attach_jvm() echo "Attaching to ${TARGET_PID} using version ${1}..." if [ ${TARGET_IP} = ${DEFAULT_TARGET_IP} ]; then - ${JAVA_HOME}/bin/java \ - ${ARTHAS_OPTS} ${BOOT_CLASSPATH} ${JVM_OPTS} \ + "${JAVA_HOME}"/bin/java \ + ${ARTHAS_OPTS} "${BOOT_CLASSPATH}" ${JVM_OPTS} \ -jar ${arthas_lib_dir}/arthas-core.jar \ -pid ${TARGET_PID} \ -target-ip ${TARGET_IP} \ @@ -405,8 +413,8 @@ active_console() local arthas_lib_dir=${ARTHAS_LIB_DIR}/${arthas_version}/arthas if [ "${BATCH_MODE}" = "true" ]; then - ${JAVA_HOME}/bin/java ${ARTHAS_OPTS} ${JVM_OPTS} \ - -jar ${arthas_lib_dir}/arthas-client.jar \ + "${JAVA_HOME}/bin/java" ${ARTHAS_OPTS} ${JVM_OPTS} \ + -jar "${arthas_lib_dir}/arthas-client.jar" \ ${TARGET_IP} \ -p ${TELNET_PORT} \ -f ${BATCH_SCRIPT} From 86b26477d98923bbb525fe6a07a7da3be3081bc1 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Thu, 11 Oct 2018 17:35:50 +0800 Subject: [PATCH 6/6] support Cygwin/MinGw. #212 --- bin/as.sh | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/bin/as.sh b/bin/as.sh index d623fd181a6..d6efa1ae903 100755 --- a/bin/as.sh +++ b/bin/as.sh @@ -53,6 +53,37 @@ BATCH_SCRIPT= ARTHAS_OPTS="-Djava.awt.headless=true" +OS_TYPE= +case "$(uname -s)" in + Linux*) OS_TYPE=Linux;; + Darwin*) OS_TYPE=Mac;; + CYGWIN*) OS_TYPE=Cygwin;; + MINGW*) OS_TYPE=MinGw;; + *) OS_TYPE="UNKNOWN" +esac + +# check curl/grep/awk/telent/unzip command +if ! [ -x "$(command -v curl)" ]; then + echo 'Error: curl is not installed.' >&2 + exit 1 +fi +if ! [ -x "$(command -v grep)" ]; then + echo 'Error: grep is not installed.' >&2 + exit 1 +fi +if ! [ -x "$(command -v awk)" ]; then + echo 'Error: awk is not installed.' >&2 + exit 1 +fi +if ! [ -x "$(command -v telnet)" ]; then + echo 'Error: telnet is not installed.' >&2 + exit 1 +fi +if ! [ -x "$(command -v unzip)" ]; then + echo 'Error: unzip is not installed.' >&2 + exit 1 +fi + # exit shell with err_code # $1 : err_code # $2 : err_msg @@ -109,7 +140,7 @@ reset_for_env() local IFS=$'\n' # remove \r for Cygwin - local lines=$(${JAVA_HOME}/bin/java -version 2>&1 | tr '\r' '\n') + local lines=$("${JAVA_HOME}"/bin/java -version 2>&1 | tr '\r' '\n') for line in $lines; do if [[ (-z $JAVA_VERSION) && ($line = *"version \""*) ]] then @@ -220,9 +251,10 @@ Example: ./as.sh --versions Here is the list of possible java process(es) to attatch: - -$(${JAVA_HOME}/bin/jps -l | grep -v sun.tools.jps.Jps) " + +"${JAVA_HOME}"/bin/jps -l | grep -v sun.tools.jps.Jps + } # list arthas versions @@ -302,7 +334,7 @@ parse_arguments() # backup IFS: https://github.com/alibaba/arthas/issues/128 local IFS_backup=$IFS IFS=$'\n' - CANDIDATES=($(${JAVA_HOME}/bin/jps -l | grep -v sun.tools.jps.Jps | awk '{print $0}')) + CANDIDATES=($("${JAVA_HOME}"/bin/jps -l | grep -v sun.tools.jps.Jps | awk '{print $0}')) if [ ${#CANDIDATES[@]} -eq 0 ]; then echo "Error: no available java process to attach." @@ -370,12 +402,17 @@ attach_jvm() local arthas_version=$1 local arthas_lib_dir=${ARTHAS_LIB_DIR}/${arthas_version}/arthas + # http://www.inonit.com/cygwin/faq/ + if [ "${OS_TYPE}" = "Cygwin" ]; then + arthas_lib_dir=`cygpath -wp $arthas_lib_dir` + fi + echo "Attaching to ${TARGET_PID} using version ${1}..." if [ ${TARGET_IP} = ${DEFAULT_TARGET_IP} ]; then "${JAVA_HOME}"/bin/java \ ${ARTHAS_OPTS} "${BOOT_CLASSPATH}" ${JVM_OPTS} \ - -jar ${arthas_lib_dir}/arthas-core.jar \ + -jar "${arthas_lib_dir}/arthas-core.jar" \ -pid ${TARGET_PID} \ -target-ip ${TARGET_IP} \ -telnet-port ${TELNET_PORT} \ @@ -386,6 +423,11 @@ attach_jvm() } sanity_check() { + # only Linux/Mac support ps to find process, Cygwin/MinGw may fail. + if ([ "${OS_TYPE}" != "Linux" ] && [ "${OS_TYPE}" != "Mac" ]); then + return + fi + # 0 check whether the pid exist local pid=$(ps -p ${TARGET_PID} -o pid=) if [ -z ${pid} ]; then @@ -412,6 +454,11 @@ active_console() local arthas_version=$1 local arthas_lib_dir=${ARTHAS_LIB_DIR}/${arthas_version}/arthas + # http://www.inonit.com/cygwin/faq/ + if [ "${OS_TYPE}" = "Cygwin" ]; then + arthas_lib_dir=`cygpath -wp $arthas_lib_dir` + fi + if [ "${BATCH_MODE}" = "true" ]; then "${JAVA_HOME}/bin/java" ${ARTHAS_OPTS} ${JVM_OPTS} \ -jar "${arthas_lib_dir}/arthas-client.jar" \ @@ -420,6 +467,14 @@ active_console() -f ${BATCH_SCRIPT} elif type telnet 2>&1 >> /dev/null; then # use telnet + if [[ $(command -v telnet) == *"system32"* ]] ; then + # Windows/system32/telnet.exe can not run in Cygwin/MinGw + echo "It seems that current bash is under Windows. $(command -v telnet) can not run under bash." + echo "Please start cmd.exe from Windows start menu, and then run telnet ${TARGET_IP} ${TELNET_PORT} to connect to target process." + echo "Or visit http://localhost:8563/ to connect to target process." + return 1 + fi + echo "telnet connecting to arthas server... current timestamp is `date +%s`" telnet ${TARGET_IP} ${TELNET_PORT} else echo "'telnet' is required." 1>&2 @@ -468,7 +523,6 @@ main() echo "Attach success." if [ ${ATTACH_ONLY} = false ]; then - echo "Connecting to arthas server... current timestamp is `date +%s`" active_console ${arthas_local_version} fi }