diff --git a/arthas-boot.jar b/arthas-boot.jar index 8c0c983cf..e1a7e2e41 100644 Binary files a/arthas-boot.jar and b/arthas-boot.jar differ diff --git a/arthas-demo.jar b/arthas-demo.jar index ac3264bf2..cf9074674 100644 Binary files a/arthas-demo.jar and b/arthas-demo.jar differ diff --git a/as.sh b/as.sh index 827cc3d36..0301a4bfb 100755 --- a/as.sh +++ b/as.sh @@ -8,12 +8,74 @@ # program : Arthas # author : Core Engine @ Taobao.com -# date : 2019-05-15 +# date : 2019-09-09 # current arthas script version -ARTHAS_SCRIPT_VERSION=3.1.1 +ARTHAS_SCRIPT_VERSION=3.1.2 -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +# SYNOPSIS +# rreadlink +# DESCRIPTION +# Resolves to its ultimate target, if it is a symlink, and +# prints its canonical path. If it is not a symlink, its own canonical path +# is printed. +# A broken symlink causes an error that reports the non-existent target. +# LIMITATIONS +# - Won't work with filenames with embedded newlines or filenames containing +# the string ' -> '. +# COMPATIBILITY +# This is a fully POSIX-compliant implementation of what GNU readlink's +# -e option does. +# EXAMPLE +# In a shell script, use the following to get that script's true directory of origin: +# trueScriptDir=$(dirname -- "$(rreadlink "$0")") +rreadlink() ( # Execute the function in a *subshell* to localize variables and the effect of `cd`. + + target=$1 fname= targetDir= CDPATH= + + # Try to make the execution environment as predictable as possible: + # All commands below are invoked via `command`, so we must make sure that + # `command` itself is not redefined as an alias or shell function. + # (Note that command is too inconsistent across shells, so we don't use it.) + # `command` is a *builtin* in bash, dash, ksh, zsh, and some platforms do not + # even have an external utility version of it (e.g, Ubuntu). + # `command` bypasses aliases and shell functions and also finds builtins + # in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for + # that to happen. + { \unalias command; \unset -f command; } >/dev/null 2>&1 + [ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find *builtins* with `command` too. + + while :; do # Resolve potential symlinks until the ultimate target is found. + [ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." >&2; return 1; } + command cd "$(command dirname -- "$target")" # Change to target dir; necessary for correct resolution of target path. + fname=$(command basename -- "$target") # Extract filename. + [ "$fname" = '/' ] && fname='' # !! curiously, `basename /` returns '/' + if [ -L "$fname" ]; then + # Extract [next] target path, which may be defined + # *relative* to the symlink's own directory. + # Note: We parse `ls -l` output to find the symlink target + # which is the only POSIX-compliant, albeit somewhat fragile, way. + target=$(command ls -l "$fname") + target=${target#* -> } + continue # Resolve [next] symlink target. + fi + break # Ultimate target reached. + done + targetDir=$(command pwd -P) # Get canonical dir. path + # Output the ultimate target's canonical path. + # Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path. + if [ "$fname" = '.' ]; then + command printf '%s\n' "${targetDir%/}" + elif [ "$fname" = '..' ]; then + # Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied + # AFTER canonicalization. + command printf '%s\n' "$(command dirname -- "${targetDir}")" + else + command printf '%s\n' "${targetDir%/}/$fname" + fi +) + +DIR=$(dirname -- "$(rreadlink "${BASH_SOURCE[0]}")") ############ Command Arguments ############ @@ -66,6 +128,11 @@ COMMAND= # batch file to execute BATCH_FILE= +# tunnel server url +TUNNEL_SERVER= +# agent id +AGENT_ID= + ############ Command Arguments ############ # if arguments contains -c/--command or -f/--batch-file, BATCH_MODE will be true @@ -150,68 +217,6 @@ check_permission() } -# SYNOPSIS -# rreadlink -# DESCRIPTION -# Resolves to its ultimate target, if it is a symlink, and -# prints its canonical path. If it is not a symlink, its own canonical path -# is printed. -# A broken symlink causes an error that reports the non-existent target. -# LIMITATIONS -# - Won't work with filenames with embedded newlines or filenames containing -# the string ' -> '. -# COMPATIBILITY -# This is a fully POSIX-compliant implementation of what GNU readlink's -# -e option does. -# EXAMPLE -# In a shell script, use the following to get that script's true directory of origin: -# trueScriptDir=$(dirname -- "$(rreadlink "$0")") -rreadlink() ( # Execute the function in a *subshell* to localize variables and the effect of `cd`. - - target=$1 fname= targetDir= CDPATH= - - # Try to make the execution environment as predictable as possible: - # All commands below are invoked via `command`, so we must make sure that - # `command` itself is not redefined as an alias or shell function. - # (Note that command is too inconsistent across shells, so we don't use it.) - # `command` is a *builtin* in bash, dash, ksh, zsh, and some platforms do not - # even have an external utility version of it (e.g, Ubuntu). - # `command` bypasses aliases and shell functions and also finds builtins - # in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for - # that to happen. - { \unalias command; \unset -f command; } >/dev/null 2>&1 - [ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find *builtins* with `command` too. - - while :; do # Resolve potential symlinks until the ultimate target is found. - [ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." >&2; return 1; } - command cd "$(command dirname -- "$target")" # Change to target dir; necessary for correct resolution of target path. - fname=$(command basename -- "$target") # Extract filename. - [ "$fname" = '/' ] && fname='' # !! curiously, `basename /` returns '/' - if [ -L "$fname" ]; then - # Extract [next] target path, which may be defined - # *relative* to the symlink's own directory. - # Note: We parse `ls -l` output to find the symlink target - # which is the only POSIX-compliant, albeit somewhat fragile, way. - target=$(command ls -l "$fname") - target=${target#* -> } - continue # Resolve [next] symlink target. - fi - break # Ultimate target reached. - done - targetDir=$(command pwd -P) # Get canonical dir. path - # Output the ultimate target's canonical path. - # Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path. - if [ "$fname" = '.' ]; then - command printf '%s\n' "${targetDir%/}" - elif [ "$fname" = '..' ]; then - # Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied - # AFTER canonicalization. - command printf '%s\n' "$(command dirname -- "${targetDir}")" - else - command printf '%s\n' "${targetDir%/}/$fname" - fi -) - # reset arthas work environment # reset some options for env reset_for_env() @@ -395,6 +400,7 @@ usage() Usage: $0 [-h] [--target-ip ] [--telnet-port ] [--http-port ] [--session-timeout ] [--arthas-home ] + [--tunnel-server ] [--agent-id ] [--use-version ] [--repo-mirror ] [--versions] [--use-http] [--attach-only] [-c ] [-f ] [-v] [pid] @@ -412,6 +418,8 @@ Options and Arguments: --use-http Enforce use http to download, default use https --attach-only Attach target process only, do not connect --debug-attach Debug attach agent + --tunnel-server Remote tunnel server url + --agent-id Special agent id -c,--command Command to execute, multiple commands separated by ; -f,--batch-file The batch file to execute @@ -424,9 +432,11 @@ EXAMPLES: ./as.sh ./as.sh --target-ip 0.0.0.0 ./as.sh --telnet-port 9999 --http-port -1 + ./as.sh --tunnel-server 'ws://192.168.10.11:7777/ws' + ./as.sh --tunnel-server 'ws://192.168.10.11:7777/ws' --agent-id bvDOe8XbTM2pQWjF4cfw ./as.sh -c 'sysprop; thread' ./as.sh -f batch.as - ./as.sh --use-version 3.1.1 + ./as.sh --use-version 3.1.2 ./as.sh --session-timeout 3600 ./as.sh --attach-only ./as.sh --repo-mirror aliyun --use-http @@ -519,6 +529,16 @@ parse_arguments() shift # past argument shift # past value ;; + --tunnel-server) + TUNNEL_SERVER="$2" + shift # past argument + shift # past value + ;; + --agent-id) + AGENT_ID="$2" + shift # past argument + shift # past value + ;; --use-http) USE_HTTP=true shift # past argument @@ -652,13 +672,13 @@ parse_arguments() # check the process already using telnet port if equals to target pid if [[ ($telnetPortPid) && ($TARGET_PID != $telnetPortPid) ]]; then echo "[ERROR] Target process $TARGET_PID is not the process using port $TELNET_PORT, you will connect to an unexpected process." - echo "[ERROR] 1. Try to restart as.sh, select process $telnetPortPid, shutdown it first." + echo "[ERROR] 1. Try to restart as.sh, select process $telnetPortPid, shutdown it first with running the 'shutdown' command." echo "[ERROR] 2. Try to use different telnet port, for example: as.sh --telnet-port 9998 --http-port -1" exit 1 fi if [[ ($httpPortPid) && ($TARGET_PID != $httpPortPid) ]]; then echo "Target process $TARGET_PID is not the process using port $HTTP_PORT, you will connect to an unexpected process." - echo "1. Try to restart as.sh, select process $httpPortPid, shutdown it first." + echo "1. Try to restart as.sh, select process $httpPortPid, shutdown it first with running the 'shutdown' command." echo "2. Try to use different http port, for example: as.sh --telnet-port 9998 --http-port 9999" exit 1 fi @@ -685,6 +705,16 @@ attach_jvm() java_command+=("${BOOT_CLASSPATH}") fi + local tempArgs=() + if [ "${TUNNEL_SERVER}" ]; then + tempArgs+=("-tunnel-server") + tempArgs+=("${TUNNEL_SERVER}") + fi + if [ "${AGENT_ID}" ]; then + tempArgs+=("-agent-id") + tempArgs+=("${AGENT_ID}") + fi + "${java_command[@]}" \ ${ARTHAS_OPTS} ${JVM_OPTS} \ -jar "${arthas_lib_dir}/arthas-core.jar" \ @@ -693,6 +723,7 @@ attach_jvm() -telnet-port ${TELNET_PORT} \ -http-port ${HTTP_PORT} \ -session-timeout ${SESSION_TIMEOUT} \ + "${tempArgs[@]}" \ -core "${arthas_lib_dir}/arthas-core.jar" \ -agent "${arthas_lib_dir}/arthas-agent.jar"