forked from async-profiler/async-profiler
-
Notifications
You must be signed in to change notification settings - Fork 1
/
jattach.sh
executable file
·167 lines (151 loc) · 3.73 KB
/
jattach.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/bin/sh
set -eu
usage() {
echo "Usage: $0 [action] <pid>"
echo "Actions:"
echo " start start agent and return immediately"
echo " stop stop agent"
echo ""
echo "<pid> is a numeric process ID of the target JVM"
echo " or 'jps' keyword to find running JVM automatically"
echo " or the application's name as it would appear in the jps tool"
echo ""
echo "Example: $0 start 3456"
echo " $0 stop 3456"
exit 1
}
mirror_output() {
# Mirror output from temporary file to local terminal
if [ "$USE_TMP" = true ]; then
if [ -f "$FILE" ]; then
cat "$FILE"
rm "$FILE"
elif [ -f "$ROOT_PREFIX$FILE" ]; then
cat "$ROOT_PREFIX$FILE"
rm "$ROOT_PREFIX$FILE"
fi
fi
}
mirror_log() {
# Try to access the log file both directly and through /proc/[pid]/root,
# in case the target namespace differs
if [ -f "$LOG" ]; then
cat "$LOG"
rm "$LOG"
elif [ -f "$ROOT_PREFIX$LOG" ]; then
cat "$ROOT_PREFIX$LOG"
rm "$ROOT_PREFIX$LOG"
fi
}
check_if_terminated() {
if ! kill -0 "$PID" 2> /dev/null; then
mirror_output
exit 0
fi
}
jcopy() {
"$JCOPY" "$PID" "$SRC_DIR" "$DST_DIR"
}
jattach() {
if [ ! -f "$ROOT_PREFIX$DST_DIR/$AGENT_JAR" ];then
exit 0
fi
set +e
echo "$1"
"$JATTACH" "$PID" load instrument false "$DST_DIR/$AGENT_JAR=$1,log=$LOG" > /dev/null
RET=$?
# Check if jattach failed
if [ $RET -ne 0 ]; then
if [ $RET -eq 255 ]; then
echo "Failed to inject agent into $PID"
fi
mirror_log
exit $RET
fi
mirror_log
mirror_output
set -e
}
SCRIPT_BIN="$0"
while [ -h "$SCRIPT_BIN" ]; do
SCRIPT_BIN="$(readlink "$SCRIPT_BIN")"
done
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_BIN")" > /dev/null 2>&1; pwd -P)"
JATTACH=$SCRIPT_DIR/build/jattach
JCOPY=$SCRIPT_DIR/build/jcopy
AGENT_JAR=apm-all.jar
SRC_DIR=$SCRIPT_DIR/agent/apm-all
DST_DIR=/tmp/kindling
ACTION="start"
FILE=""
USE_TMP="true"
PID=""
while [ $# -gt 0 ]; do
case $1 in
-h|"-?")
usage
;;
start|stop)
ACTION="$1"
;;
[0-9]*)
PID="$1"
;;
-*)
echo "Unrecognized option: $1"
usage
;;
*)
if [ $# -eq 1 ]; then
# the last argument is the application name as it would appear in the jps tool
PID=$(jps -J-XX:+PerfDisableSharedMem | grep " $1$" | head -n 1 | cut -d ' ' -f 1)
if [ "$PID" = "" ]; then
echo "No Java process '$1' could be found!"
fi
else
echo "Unrecognized option: $1"
usage
fi
;;
esac
shift
done
if [ "$PID" = "" ]; then
case "$ACTION" in
*)
usage
;;
esac
exit 0
fi
# If no -f argument is given, use temporary file to transfer output to caller terminal.
# Let the target process create the file in case this script is run by superuser.
if [ "$USE_TMP" = true ]; then
FILE=/tmp/jattach.$$.$PID
else
case "$FILE" in
/*)
# Path is absolute
;;
*)
# Output file is written by the target process. Make the path absolute to avoid confusion.
FILE=$PWD/$FILE
;;
esac
fi
LOG=/tmp/jattach-log.$$.$PID
UNAME_S=$(uname -s)
if [ "$UNAME_S" = "Linux" ]; then
ROOT_PREFIX="/proc/$PID/root"
else
ROOT_PREFIX=""
fi
case $ACTION in
start)
jcopy
jattach "$ACTION,file=$FILE"
;;
stop)
jattach "$ACTION,file=$FILE"
;;
esac