]>
Commit | Line | Data |
---|---|---|
d885563b FCE |
1 | #!/bin/bash |
2 | ||
3 | # $1 - install/uninstall | |
4 | # $2 - PID/unique name | |
5 | # $3 - RULE name | |
6 | # $4 - class | |
7 | # $5 - method | |
8 | # $6 - number of args | |
9 | # $7 - entry/exit/line | |
6ded984a | 10 | # $8 - backtrace trigger |
d885563b FCE |
11 | |
12 | exec 1>&2 # redirect byteman/etc. tracing output to stderr, for easier filtering | |
13 | ||
6ded984a LB |
14 | if [[ $# -gt 8 || $# -lt 7 ]]; then |
15 | echo "need seven or eight arguments" | |
d885563b FCE |
16 | exit 1 |
17 | fi | |
18 | ||
19 | arg_command=$1 | |
20 | arg_jvmpid=$2 | |
21 | arg_rulename=$3 | |
22 | arg_class=$4 | |
23 | arg_method=$5 | |
24 | arg_argcount=$6 | |
25 | arg_probetype=$7 | |
26 | ||
6ded984a LB |
27 | if [ $# -eq 7 ]; then |
28 | arg_backtrace=0 | |
29 | else | |
30 | arg_backtrace=$8 | |
31 | fi | |
32 | ||
d885563b FCE |
33 | SYSTEMTAP_DIR=${SYSTEMTAP_DIR-$HOME/.systemtap} |
34 | BYTEMAN_HOME=${BYTEMAN_HOME-/usr/share/java/byteman} | |
35 | JAVA_HOME=${JAVA_HOME-/usr/lib/jvm/java} | |
296dbeb1 | 36 | BYTEMAN_INSTALL_OPTS=${BYTEMAN_INSTALL_OPTS--Dorg.jboss.byteman.transform.all=true} |
c31d198c | 37 | SYSTEMTAP_VERBOSE=${SYSTEMTAP_VERBOSE-0} |
296dbeb1 | 38 | |
c31d198c | 39 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then |
296dbeb1 FCE |
40 | BYTEMAN_INSTALL_OPTS="$BYTEMAN_INSTALL_OPTS -Dorg.jboss.byteman.verbose" |
41 | else | |
42 | exec >/dev/null 2>&1 | |
43 | fi | |
d885563b | 44 | |
d885563b FCE |
45 | # the byteman and byteman-submit jars should be in ${BYTEMAN_HOME}/lib |
46 | BYTEMAN_JAR=${BYTEMAN_HOME}/byteman.jar | |
47 | if [ ! -r ${BYTEMAN_JAR} ]; then | |
6ded984a | 48 | echo "Missing $BYTEMAN_JAR" |
d885563b FCE |
49 | exit 1 |
50 | fi | |
51 | ||
52 | BYTEMAN_SUBMIT_JAR=${BYTEMAN_HOME}/byteman-submit.jar | |
53 | if [ ! -r ${BYTEMAN_SUBMIT_JAR} ]; then | |
54 | echo "Missing $BYTEMAN_SUBMIT_JAR" | |
55 | exit 1 | |
56 | fi | |
57 | ||
58 | BYTEMAN_INSTALL_JAR=${BYTEMAN_HOME}/byteman-install.jar | |
59 | if [ ! -r ${BYTEMAN_INSTALL_JAR} ]; then | |
60 | echo "Missing $BYTEMAN_INSTALL_JAR" | |
61 | exit 1 | |
62 | fi | |
63 | ||
d885563b FCE |
64 | |
65 | TOOLS_JAR=${JAVA_HOME}/lib/tools.jar | |
66 | if [ ! -f ${TOOLS_JAR} ]; then | |
67 | echo "Missing $TOOLS_JAR" | |
68 | exit 1 | |
69 | fi | |
70 | ||
71 | # resolve $*prefix fully | |
72 | prefix=@prefix@ | |
73 | exec_prefix=@exec_prefix@ | |
74 | pkglibexecdir=@libexecdir@/@PACKAGE@ | |
75 | pkglibexecdir=`eval echo $pkglibexecdir` | |
76 | pkglibexecdir=`eval echo $pkglibexecdir` | |
77 | ||
78 | num=`ls -1 ${JAVA_HOME}/jre/lib/ext/HelperSDT.jar ${JAVA_HOME}/jre/lib/*/libHelperSDT_*.so 2>/dev/null | wc -l` | |
79 | if [ $num -lt 2 ]; then | |
80 | echo "Missing HelperSDT JNI class/shared library" | |
81 | echo "Install them like this, as root:" | |
82 | echo "" | |
83 | echo "for so in ${pkglibexecdir}/libHelperSDT_*.so; do" | |
84 | echo ' arch=`basename $so | cut -f2 -d_ | cut -f1 -d.`' | |
85 | echo " ln -sf ${pkglibexecdir}/libHelperSDT_"'${arch}'".so ${JAVA_HOME}/jre/lib/"'${arch}'"/" | |
86 | echo "done" | |
87 | echo "ln -sf ${pkglibexecdir}/HelperSDT.jar ${JAVA_HOME}/jre/lib/ext/" | |
88 | exit 1 | |
89 | fi | |
90 | ||
91 | flagdir="$SYSTEMTAP_DIR/java" | |
92 | mkdir -p $flagdir | |
93 | ||
269cd0ae LB |
94 | # Find our target jvm pid. Due to the possibility of our |
95 | # target jvm pid being passed as a string, we need to allow | |
96 | # for the possiblity that more than one pid may match the | |
97 | # target jvm pid. If this is the case, we need to have a | |
98 | # nested call to stapbm with the actual pid of the jvm pid | |
99 | ||
c226c5cc | 100 | if ! [[ $arg_jvmpid =~ ^[0-9]+$ ]]; then |
269cd0ae LB |
101 | target_pid=`jps -l | grep $arg_jvmpid | cut -f1 -d" "` |
102 | for target in $target_pid; do | |
0782191d | 103 | $0 $arg_command $target $arg_rulename $arg_class "$arg_method" $arg_argcount $arg_probetype $arg_backtrace |
269cd0ae LB |
104 | done; |
105 | exit 0 | |
106 | else | |
107 | target_pid=$arg_jvmpid | |
d885563b FCE |
108 | fi |
109 | ||
110 | # Our target jvm may not have the byteman agent installed yet. Let's do | |
111 | # that first. We use a signal file in $flagdir to show that the | |
112 | # JVM is ready for further bytemanning without a prior setup step, | |
113 | # and include in it the designated byteman agent listening-port number. | |
114 | # | |
115 | byteman_installed_portfile=$flagdir/`hostname`-${target_pid}-bm | |
116 | ||
117 | exec 200>>$byteman_installed_portfile # open/create lock file | |
118 | flock -x 200 # exclusive-lock it | |
119 | ||
120 | if [ -s $byteman_installed_portfile ]; then | |
121 | bmport=`cat $byteman_installed_portfile` | |
296dbeb1 | 122 | |
c31d198c | 123 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then |
296dbeb1 FCE |
124 | echo "Byteman agent reused for java pid $target_pid, port $bmport" |
125 | fi | |
126 | ||
6ded984a | 127 | |
d885563b FCE |
128 | # XXX: liveness-check the port; bmsubmit with no argument just lists current rules |
129 | # if fails, delete the _portfile and retry everything | |
130 | else | |
131 | # bmport=9091 | |
132 | bmport=`expr 9090 + $RANDOM % 10000` | |
133 | existing=`netstat -atn | awk '{print $4}' | grep ':'$bmport'$'` | |
134 | if [ "x$existing" != "x" ]; then | |
135 | echo "Byteman port $bmport already in use, retrying." | |
136 | exec "$@" | |
137 | fi | |
8eef2738 | 138 | |
70ff58b7 LB |
139 | # There are two ways to invoke and run byteman operations with the jvm's we're interested |
140 | # in, we can alter the startup arguments to include a -javaagent parameter, or use | |
6ded984a | 141 | # byteman and its use of VMAttach libraries, for our case it always makes sense to use |
70ff58b7 | 142 | # byteman classes directly and avoid -javaagent |
8eef2738 | 143 | |
c31d198c | 144 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then |
70ff58b7 | 145 | echo java -classpath ${BYTEMAN_INSTALL_JAR}:${BYTEMAN_JAR}:${TOOLS_JAR} org.jboss.byteman.agent.install.Install -b -p $bmport $BYTEMAN_INSTALL_OPTS $target_pid |
296dbeb1 | 146 | fi |
70ff58b7 | 147 | java -classpath ${BYTEMAN_INSTALL_JAR}:${BYTEMAN_JAR}:${TOOLS_JAR} org.jboss.byteman.agent.install.Install -b -p $bmport $BYTEMAN_INSTALL_OPTS $target_pid |
d885563b FCE |
148 | if [ $? -ne 0 ]; then |
149 | echo "Byteman agent failed to install for java pid $target_pid, port $bmport" | |
150 | exit 1 | |
151 | fi | |
152 | echo $bmport > $byteman_installed_portfile | |
153 | ||
c31d198c | 154 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then |
296dbeb1 FCE |
155 | echo "Byteman agent installed for java pid $target_pid, port $bmport" |
156 | fi | |
d885563b FCE |
157 | # XXX: Erase file to keep it from sticking around indefinitely, |
158 | # in case process ends, machine reboots, pid gets reused | |
159 | # XXX: consider explicit notification to stapbm via process("java").begin/end ? | |
160 | # ... or else: liveness-check below | |
161 | fi | |
162 | exec 200>&- # close file & release flock | |
163 | ||
164 | ||
165 | function echo_bytemanrule() | |
166 | { | |
167 | echo "RULE $arg_rulename" | |
168 | echo "CLASS $arg_class" | |
169 | echo "METHOD $arg_method" | |
8eef2738 | 170 | echo "HELPER org.systemtap.byteman.helper.HelperSDT" |
d885563b FCE |
171 | case "$arg_probetype" in |
172 | entry) | |
173 | echo "AT ENTRY" | |
174 | ;; | |
175 | exi*) | |
176 | echo "AT RETURN" | |
177 | ;; | |
178 | *) | |
179 | echo "AT LINE $arg_probetype" | |
180 | ;; | |
181 | esac | |
182 | echo "IF TRUE" | |
6ded984a LB |
183 | if [ "$arg_backtrace" == "1" ]; then |
184 | echo 'DO STAP_BACKTRACE("'$arg_rulename'");' | |
185 | else | |
186 | echo -n 'DO ' | |
187 | fi | |
d885563b | 188 | case "$arg_argcount" in |
6ded984a LB |
189 | 0) echo -n 'METHOD_STAP_PROBE0("'$arg_rulename'")' ;; |
190 | 1) echo -n 'METHOD_STAP_PROBE1("'$arg_rulename'", $1)' ;; | |
191 | 2) echo -n 'METHOD_STAP_PROBE2("'$arg_rulename'", $1, $2)' ;; | |
192 | 3) echo -n 'METHOD_STAP_PROBE3("'$arg_rulename'", $1, $2, $3)' ;; | |
193 | 4) echo -n 'METHOD_STAP_PROBE4("'$arg_rulename'", $1, $2, $3, $4)' ;; | |
194 | 5) echo -n 'METHOD_STAP_PROBE5("'$arg_rulename'", $1, $2, $3, $4, $5)' ;; | |
195 | 6) echo -n 'METHOD_STAP_PROBE6("'$arg_rulename'", $1, $2, $3, $4, $5, $6)' ;; | |
196 | 7) echo -n 'METHOD_STAP_PROBE7("'$arg_rulename'", $1, $2, $3, $4, $5, $6, $7)' ;; | |
197 | 8) echo -n 'METHOD_STAP_PROBE8("'$arg_rulename'", $1, $2, $3, $4, $5, $6, $7, $8)' ;; | |
198 | 9) echo -n 'METHOD_STAP_PROBE9("'$arg_rulename'", $1, $2, $3, $4, $5, $6, $7, $8, $9)' ;; | |
199 | 10) echo -n 'METHOD_STAP_PROBE10("'$arg_rulename'", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10)' ;; | |
d885563b FCE |
200 | *) echo 'bad arg-count'; exit 1 ;; |
201 | esac | |
6ded984a LB |
202 | if [ "$arg_backtrace" == "1" ]; then |
203 | echo ';' | |
204 | echo 'METHOD_BT_DELETE("'$arg_rulename'")' | |
205 | else | |
206 | echo '' | |
207 | fi | |
d885563b FCE |
208 | echo "ENDRULE" |
209 | } | |
210 | ||
211 | ||
212 | # Generate the byteman rule file on-the-fly | |
213 | btmfile=$flagdir/`hostname`-$$.btm | |
214 | echo_bytemanrule > $btmfile | |
215 | trap 'rm -f $btmfile' 0 1 2 3 4 5 9 15 | |
216 | ||
c31d198c | 217 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then |
296dbeb1 FCE |
218 | echo "Byteman rule file:" |
219 | cat $btmfile | |
220 | fi | |
221 | ||
d885563b FCE |
222 | if [ $arg_command = "uninstall" ]; then |
223 | bmcmd=-u | |
224 | else | |
225 | bmcmd=-l | |
226 | fi | |
227 | ||
c31d198c | 228 | if [ "$SYSTEMTAP_VERBOSE" != "0" ]; then |
70ff58b7 | 229 | echo java -classpath ${BYTEMAN_SUBMIT_JAR}:${BYTEMAN_JAR} org.jboss.byteman.agent.submit.Submit -p $bmport $bmcmd $btmfile |
296dbeb1 | 230 | fi |
e2a412fa | 231 | |
70ff58b7 | 232 | exec java -classpath ${BYTEMAN_SUBMIT_JAR}:${BYTEMAN_JAR} org.jboss.byteman.agent.submit.Submit -p $bmport $bmcmd $btmfile |