summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2009-01-30 18:54:06 -0500
committerMasami Hiramatsu <mhiramat@redhat.com>2009-01-30 18:54:06 -0500
commit9a8d8be369cd1d2ac148b367e1c4b74ab9a005ba (patch)
treeeee895a1ac6b4a94f268647b031708fc17e102dc
parent255b5e73f14c9fc72e5566edf595ab8df184f14f (diff)
downloadsystemtap-steved-9a8d8be369cd1d2ac148b367e1c4b74ab9a005ba.tar.gz
systemtap-steved-9a8d8be369cd1d2ac148b367e1c4b74ab9a005ba.tar.xz
systemtap-steved-9a8d8be369cd1d2ac148b367e1c4b74ab9a005ba.zip
PR6936: Add systemtap initscript and systemtap-initscript subpackage.
-rw-r--r--ChangeLog7
-rw-r--r--NEWS5
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac2
-rw-r--r--initscript/ChangeLog6
-rw-r--r--initscript/README.initscript355
-rw-r--r--initscript/config20
-rw-r--r--initscript/systemtap.in664
-rw-r--r--systemtap.spec40
9 files changed, 1100 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 62708e24..618588a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-01-30 Masami Hiramatsu <mhiramat@redhat.com>
+
+ PR6936
+ * configure.ac (AC_CONFIG_FILES): Add initscript/systemtap.in.
+ * configure: Regenerated.
+ * systemtap.spec: Add systemtap-initscript subpackage.
+
2009-01-30 Dave Brolley <brolley@redhat.com>
* Makefile.am (install-scripts): New target. Set exec_prefix and
diff --git a/NEWS b/NEWS
index 47d4199b..25ebcccf 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,10 @@
* What's new
+- Systemtap initscript is available. This initscript allows you to run
+ systemtap scripts as system services (in flight recorder mode) and
+ control those scripts individually.
+ See README.initscript for details.
+
- The stap "-r DIR" option may be used to identify a hand-made kernel
build directory. The tool determines the appropriate release string
automatically from the directory.
diff --git a/configure b/configure
index 4f63ffda..7bf7bb14 100755
--- a/configure
+++ b/configure
@@ -7937,7 +7937,7 @@ _ACEOF
ac_config_headers="$ac_config_headers config.h:config.in"
-ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 stap-server.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5"
+ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 stap-server.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5 initscript/systemtap"
@@ -8644,6 +8644,7 @@ do
"man/stapprobes.socket.5") CONFIG_FILES="$CONFIG_FILES man/stapprobes.socket.5" ;;
"man/stapprobes.tcp.5") CONFIG_FILES="$CONFIG_FILES man/stapprobes.tcp.5" ;;
"man/stapprobes.udp.5") CONFIG_FILES="$CONFIG_FILES man/stapprobes.udp.5" ;;
+ "initscript/systemtap") CONFIG_FILES="$CONFIG_FILES initscript/systemtap" ;;
"run-stap") CONFIG_FILES="$CONFIG_FILES run-stap" ;;
*) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
diff --git a/configure.ac b/configure.ac
index a0d18c29..542b3b48 100644
--- a/configure.ac
+++ b/configure.ac
@@ -335,7 +335,7 @@ dnl Don't use this directly (when not given it is set to NONE).
AC_DEFINE_UNQUOTED(STAP_PREFIX, "$prefix", [configure prefix location])
AC_CONFIG_HEADERS([config.h:config.in])
-AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 stap-server.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5)
+AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.5 stapfuncs.5 stapvars.5 stapex.5 staprun.8 stap-server.8 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.socket.5 man/stapprobes.tcp.5 man/stapprobes.udp.5 initscript/systemtap)
AC_CONFIG_SUBDIRS(testsuite)
AC_CONFIG_FILES([run-stap], [chmod +x run-stap])
AC_OUTPUT
diff --git a/initscript/ChangeLog b/initscript/ChangeLog
new file mode 100644
index 00000000..3672a901
--- /dev/null
+++ b/initscript/ChangeLog
@@ -0,0 +1,6 @@
+2009-01-30 Masami Hiramatsu <mhiramat@redhat.com>
+
+ PR6936
+ * systemtap.in: First commit of systemtap initscript.
+ * README.initscript: Ditto.
+ * config: Ditto.
diff --git a/initscript/README.initscript b/initscript/README.initscript
new file mode 100644
index 00000000..f566cf71
--- /dev/null
+++ b/initscript/README.initscript
@@ -0,0 +1,355 @@
+Systemtap initscript
+Version 0.2
+Author: Masami Hiramatsu <mhiramat@redhat.com>
+
+INDEX
+=====
+1. Introduction
+2. Usage
+3. Files
+4. Configuration Format
+5. How to use
+
+1. Introduction
+===============
+Systemtap initscript aims to provide
+- running systemtap script as a service with dependency.
+- easy way to control(start/stop) those scripts individually.
+The dependency means that which user-defined systemtap script is required by
+other script (Here the scripts don't include tapsets). This dependency
+will be useful for users who use -DRELAY_HOST and -DRELAY_GUEST.
+
+2. Usage
+========
+2.1 Synopsis
+
+/sbin/service systemtap {start|stop|restart|status|compile|cleanup} \
+ [-r kernelrelease] [-c config] [-R] [-y] [script(s)]
+
+2.2 Commands
+ You have to specify one of the below commands.
+
+2.2.1 start
+ Run script(s). If the script(s) is already started, the command will be
+ ignored. If it fails to start, return FAIL. If AUTOCOMPILE option is 'yes'
+ (see 4.1.9), this will try to compile or update the specified script when
+ one of the below condition is true.
+ - compiled cache file does not exist.
+ - mtime (modified time stamp) of original script file is newer than compiled
+ script cache.
+ - script options which is used when compiling(see 4.2.1) has been changed.
+ - result of `uname -a` has been changed.
+ If no scripts specified from command line, it starts all scripts in the script
+ directory or the scripts specified by DEFAULT_START in config (see 4.1.10).
+
+2.2.2 stop
+ Stop script(s). If the script(s) is already stopped, this will be ignored.
+ If it fails to stop, return FAIL.
+ If no scripts specified from command line, it stops all running scripts.
+
+2.2.3 restart
+ Stop and start script(s) again.
+
+2.2.4 status
+ Show running script(s) status and dependency.
+
+2.2.5 compile
+ Compile script(s) on the specified kernel. This command takes '-r' option
+ which specifies the release of the kernel(see 2.3.4) on which you would
+ like to compile script(s). This command asks user whether it can overwrite
+existing caches.
+
+2.2.6 cleanup
+ Cleanup compiled script(s) from cache directory(see 3.4). This command also
+ takes '-r' option. If '-r' option is omitted, cleanup all caches for running
+ kernel. This command asks user whether it can remove caches.
+
+2.3 Options
+ Systemtap initscript can have some options. However, since user can't pass
+ these options on boot, these options are only for testing or managing scripts
+ after booting.
+
+2.3.1 -c config_path
+ You can specify configuration path of this initscript.
+
+2.3.2 script(s)
+ You can specify individual scripts to the commands. If you omit to specify
+ any script, systemtap initscript will execute the command with all scripts
+ in the script directory(except 'start' and 'stop' command, see 2.2.1 and
+ 2.2.2).
+
+2.3.3 -R
+ If this option is specified, systemtap initscript will try to solve
+ dependency of specified script(s). This option is always set if you don't
+ specify any script(s) from command line.
+
+2.3.4 -r kernelrelease
+ You can specify release version of the kernel(e.g. 2.6.26.1). This option
+ is valid only with compile and cleanup commands.
+
+2.3.5 -y
+ Answer yes for all questions.
+
+2.4 Misc
+2.4.1 Service Priority
+ Each initscript has execution priority. Since user would like to trace
+ other services by using systemtap, systemtap initscript should have the
+ highest priority.
+
+3. Files
+========
+3.1 initscript
+ /etc/init.d/systemtap
+
+ This file is an executable bash script.
+
+3.2 Configurations
+ Configuration files are written in bash script.
+
+3.2.1 Global config file
+ /etc/systemtap/config
+
+ This config file is for global parameters(see 4.1).
+
+3.2.2 Script config files
+ /etc/systemtap/conf.d/*.conf
+
+ The config files under this directory are for each scripts or script groups
+ (see 4.2).
+
+3.3 Script directory
+ /etc/systemtap/script.d/
+
+ Systemtap initscript finds systemtap scripts from this directory.
+
+3.3.1 Scripts in the directory
+ /etc/systemtap/script.d/<script-name>.stp
+
+ Systemtap scripts stored in the script directory must have ".stp" suffix.
+
+3.4 Cache directory
+ /var/cache/systemtap/<kernel-version>/
+
+ Systemtap initscript stores compiled scripts in this directory.
+
+3.4.1 Compiled scripts (or script caches)
+ /var/cache/systemtap/<kernel-version>/<script-name>.ko
+ /var/cache/systemtap/<kernel-version>/<script-name>.opts
+
+ *.ko file is the compiled script, and *.opts is the file which stores
+ stap options and uname -a.
+
+3.5 Message Log
+ /var/log/systemtap.log
+
+ All messages including compilation errors and detailed messages are sent
+ to this file.
+ Some error and warning messages are also sent to console and syslogd (syslog
+ output is optional, because this service will start before syslog).
+
+3.7 Status files
+ /var/run/systemtap/<script-name>
+
+
+4. Configuration Format
+=======================
+Configuration file allows us
+- specifying options for each script
+- supporting flight recorder mode (on file or memory)
+
+4.1 Global Parameters
+
+4.1.1 SCRIPT_PATH
+ Specify the absolute path of the script directory.
+ (default: /etc/systemtap/script.d)
+
+4.1.2 CONFIG_PATH
+ Specify the absolute path of the script config directory.
+ (default: /etc/systemtap/conf.d)
+
+4.1.3 CACHE_PATH
+ Specify the absolute path of the parent directory of the cache directory.
+ (default: /var/cache/systemtap)
+
+4.1.4 TEMP_PATH
+ Specify the absolute path of the temporary directory on which systemtap
+ initscript make temporary directories to compile scripts.
+ (default: /tmp)
+
+4.1.5 STAT_PATH
+ Specify the absolute path of the running status directory.
+ (default: /var/run/systemtap)
+
+4.1.6 LOG_FILE
+ Specify the absolute path of the log file
+ (default: /var/log/systemtap.log)
+
+4.1.7 PASSALL
+ If this is set 'yes', systemtap initscript will fail when it fails
+ to run one of the scripts. If not, systemtap initscript will not
+ fail(just warn).
+ (default: yes)
+
+4.1.8 RECURSIVE
+ If this is set 'yes', systemtap initscript will always follow script
+ dependencies. This means, you don't need to specify '-R' option. This flag is
+ effective only if you specify script(s) from command line.
+ (default: no)
+
+4.1.9 AUTOCOMPILE
+ If this is set 'yes', systemtap initscript automatically tries to compile
+ specified script if there is no valid cache. Otherwides, it just fails to
+ run script(s).
+ (default: yes)
+
+4.1.10 DEFAULT_START
+ Specify scripts which will be started by default. If omitted (or empty),
+ all scripts in the script directory will be started.
+ (default: "")
+
+4.1.11 ALLOW_CACHEONLY
+ If this is set 'yes', systemtap initscript list up cache-only scripts too.
+ *NOTE*: systemtap initscript will load unexpected obsolate caches with this
+ option. You should check cache directory before enabling this option.
+ (default: no)
+
+4.2 Script Parameters
+
+4.2.1 <script-name>_OPT
+ Specify options passed to stap command for each script. "script-name" is the
+ name of the script file without the suffix extension(.stp).
+ Some options are just ignored. And even if you don't specify -F option,
+ systemtap initscript always add it for flight recorder mode.
+ - Below options are ignored when compiling script.
+ -p,-m,-r,-c,-x,-e,-s,-o,-h,-V,-k
+ - Below options are ignored when starting script.
+ -h,-V,-M,-v,-t,-p,-I,-e,-R,-r,-m,-k,-g,-P,-D,-b,-u,-q,-w,-l,-d,-L,-F, and
+ other long options.
+
+4.2.2 <script-name>_REQ
+ Specify script dependency(which script this script requires).
+ For example, "foo.stp" script requires(or run after) "bar.stp" script, set
+
+ foo_REQ="bar"
+
+ If the script requires many scripts, set all scripts separated by spaces.
+
+ foo_REQ="bar baz"
+
+4.3 Configuration Example
+
+4.3.1 Global Config Example
+---
+SCRIPT_PATH=/var/systemtap/script.d/
+PASSALL=yes
+RECURSIVE=no
+---
+
+4.3.2 Script Config Example
+---
+script1_OPT="-o /var/log/script1.out -DRELAYHOST=group1"
+script2_OPT="-DRELAYGUEST=group1"
+script2_REQ=script1
+---
+
+5. How to use
+=============
+
+5.1 Package Installation
+ After installing systemtap package, install systemtap-initscript package.
+ # yum install systemtap-initscript
+ This package will include initscript and default configuration file and
+ other files.
+
+5.2 Script installation
+5.2.1 Installing script files
+ Copy a systemtap script ("script1.stp") into script directory.
+ # cp script1.stp /etc/systemtap/script.d/
+
+5.2.2 Configuration script options
+ Add configuration file to specify options.
+ # vi /etc/systemtap/conf.d/group1
+ script1_OPT="-o /var/log/group1.log -DRELAYHOST=group1"
+
+5.2.3 Installing script file with dependency
+ For example, a script("script2.stp") which shares buffer with another
+ script("script1.stp"), there is a dependency. In this case, you just do
+ as following.
+
+ # cp script2.stp /etc/systemtap/script.d/
+ # vi /etc/systemtap/conf.d/group1
+ script2_OPT="-DRELAYGUEST=group1"
+ script2_REQ=script1
+
+ In this case, if stap fails to run script1.stp, systemtap initscript will
+ not run script2.stp.
+
+5.3 Testing
+ After installing all scripts, please make sure to run service successfully.
+ # service systemtap start
+ # service systemtap stop
+ If there is no error, we are ready to use it.
+
+5.4 Service Enabling
+ After all test passed, enable systemtap initscript.
+ # chkconfig systemtap on
+
+5.5 Adding script
+5.5.1 Installing and configuring new scripts
+ Copy new systemtap script("script3.stp") into script directory.
+ # cp script3.stp /etc/systemtap/script.d/
+ and configure it.
+ # vi /etc/systemtap/conf.d/group1
+ script3_OPT="-DRELAYGUEST=group1"
+ script3_REQ="script1"
+
+5.5.2 Start new script
+ If you've already started systemtap initscript, just start new script.
+ # service systemtap start script3
+
+5.6 Deleting script
+5.6.1 Deleting old script
+ Remove old script ("script2.stp") and remove configure lines
+ # rm /etc/systemtap/script.d/script2.stp
+ # vi /etc/systemtap/conf.d/group1
+ (delete script2_OPT and script2_REQ)
+
+5.6.2 Stopping old script and cleanup
+ Stop old script.
+ # service systemtap stop script2
+ And cleanup the script caches.
+ # service systemtap cleanup script2
+
+5.7 Updating kernel
+ Usually, you don't need to do anything. Systemtap initscript checks the
+ kernel version when starting the service, and compile scripts.
+ (If you would like to use compiled scripts due to lack of compiler or
+ debuginfo on the system, see 5.8)
+ However, if you want to avoid compiling when booting system, you can prepare
+ script caches for new kernel.
+ # service systemtap compile -r <new kernel version>
+
+5.8 Using with compiled scripts
+ Sometimes, production systems don't have any compilation environment. Even
+ though, you can use systemtap initscript with compiled scripts as script
+ caches, which are compiled on other machine (but same software environment).
+
+5.8.1 Preparing compiled scripts
+ As described in 5.2, installing scripts and configure it on the compiling
+ machine (which has compilation environment).
+ After that, compile those scripts.
+ # service systemtap compile -r <kernel-version>
+ And package the compiled scripts and configuration file.
+ # tar czf stap-scripts-<kernel-version>.tar.gz \
+ /var/cache/systemtap/<kernel-version> /etc/systemtap/conf.d/<config>
+ And copy this package to the target machine.
+
+5.8.2 Installing pre-compiled scripts
+ On the target machine, unpackage the compiled scripts into cache
+ directory.
+ # tar xzf stap-scripts-<kernel-version>.tar.gz -C /var/cache/systemtap/
+ # mv /var/cache/systemtap/<config> /etc/systemtap/conf.d/
+ At last, set AUTOCOMPILE=no and ALLOW_CACHEONLY=yes in config file.
+ # vi /etc/systemtap/config
+ AUTOCOMPILE=no
+ ALLOW_CACHEONLY=yes
diff --git a/initscript/config b/initscript/config
new file mode 100644
index 00000000..c49a34a5
--- /dev/null
+++ b/initscript/config
@@ -0,0 +1,20 @@
+# Path setup
+# SCRIPT_PATH=/etc/systemtap/script.d
+# CONFIG_PATH=/etc/systemtap/conf.d
+# CACHE_PATH=/var/cache/systemtap
+# STAT_PATH=/var/run/systemtap
+# TEMP_PATH=/tmp
+# LOG_FILE=/var/log/systemtap.log
+
+# Fail unless all scripts succeeded to run
+# PASSALL=yes
+
+# Always follows script dependencies
+# RECURSIVE=no
+
+# Automatically recompile scripts if caches are old or do not exist.
+# AUTOCOMPILE=yes
+
+# Start these scripts by default. If omitted, all scripts are started.
+# DEFAULT_START=
+
diff --git a/initscript/systemtap.in b/initscript/systemtap.in
new file mode 100644
index 00000000..eaa1d969
--- /dev/null
+++ b/initscript/systemtap.in
@@ -0,0 +1,664 @@
+#!/bin/bash
+#
+# systemtap Startup script for systemtap scrips
+#
+# chkconfig: - 00 99
+# description: Systemtap is a programable kernel/application tracing tool.
+# config: /etc/systemtap/config
+# config: /etc/systemtap/conf.d
+### BEGIN INIT INFO
+# Provides: Systemtap scripts startup
+# Required-Start: $local_fs
+# Required-Stop: $local_fs
+# Short-Description: start and stop systemtap scripts
+# Description: Systemtap is a programable kernel/application tracing tool.
+### END INIT INFO
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+prog=systemtap
+
+# Commands
+STAP=@bindir@/stap
+STAPRUN=@bindir@/staprun
+UNAME=/bin/uname
+LSMOD=/sbin/lsmod
+
+# Path setup
+SCRIPT_PATH=/etc/systemtap/script.d
+CONFIG_PATH=/etc/systemtap/conf.d
+CACHE_PATH=/var/cache/systemtap
+STAT_PATH=/var/run/systemtap
+TEMP_PATH=/tmp
+LOG_FILE=/var/log/systemtap.log
+
+# FAIL unless all scripts succeeded to run
+PASSALL=yes
+
+# Always follows script dependencies
+RECURSIVE=no
+
+# Automatically recompile scripts if caches are old or do not exist.
+AUTOCOMPILE=yes
+
+# Start these scripts by default. If omitted, all scripts are started.
+DEFAULT_START=
+
+# Allow cache only scripts
+ALLOW_CACHEONLY=no
+
+# Optional settings
+CONFIG=/etc/systemtap/config
+SCRIPTS=
+KRELEASE=`uname -r`
+OPT_RECURSIVE=
+OPT_SCRIPTS=
+OPTS=
+OPT_ASSUMEYES=
+
+echo_usage () {
+ echo $"Usage: $prog {start|stop|restart|status|compile|cleanup} [option]"
+ echo $"Options:"
+ echo $" -c configfile : specify config file"
+ echo $" -r kernelrelease: specify kernel release version"
+ echo $" -R : recursively dependency checking"
+ echo $" -y : answer yes for all questions."
+ echo $" script(s) : specify systemtap scripts"
+}
+
+#-----------------------------------------------------------------
+# Helper functions
+#-----------------------------------------------------------------
+log () { # message
+ echo `LC_ALL=en date +"%b %e %T"`": $1" >> "$LOG_FILE"
+}
+clog () { # message [-n]
+ echo $2 $1
+ log "$1"
+}
+slog () { # message
+ logger "$1" # if syslogd is running, this message will be sent to syslog.
+ log "$1"
+}
+logex () { # command
+ eval log \"Exec: $@\"
+ "$@" >> "$LOG_FILE" 2>&1
+ return $?
+}
+do_warning () { # message
+ slog "Warning: $1"
+ warning "$1"
+}
+do_failure () { # message
+ slog "Error: $1"
+ failure "$1"
+}
+do_success () { # message
+ log "Pass: $1"
+ success "$1"
+}
+# Normalize options
+check_bool () { # value
+ case $1 in
+ n|N|no|No|NO|0)
+ return 0;;
+ y|Y|yes|Yes|YES|1)
+ return 1;;
+ *)
+ return 2;;
+ esac
+}
+ask_yesno () { # message
+ local yn ret=2
+ [ "$OPT_ASSUMEYES" ] && return 1
+ while [ $ret -eq 2 ]; do
+ echo -n "$1 [y/N]: "
+ read yn
+ [ -z "$yn" ] && return 0
+ check_bool $yn
+ ret=$?
+ done
+ return $ret
+}
+
+#------------------------------------------------------------------
+# Parameter parsing and setup options
+#------------------------------------------------------------------
+parse_args () { # arguments
+ while [ -n "$1" ]; do
+ case "$1" in
+ -c)
+ CONFIG=$2
+ shift 1
+ ;;
+ -r)
+ KRELEASE=$2
+ shift 1
+ ;;
+ -R)
+ OPT_RECURSIVE=1
+ ;;
+ -y)
+ OPT_ASSUMEYES=1
+ ;;
+ --)
+ ;;
+ *)
+ OPT_SCRIPTS=$OPT_SCRIPTS\ $1
+ ;;
+ esac
+ shift 1
+ done
+}
+
+CMD=$1
+shift 1
+OPTS=`getopt -s bash -u -o 'r:c:R' -- $@`
+if [ $? -ne 0 ]; then
+ slog "Error: Argument parse error: $@"
+ failure $"parse error"
+ echo_usage
+ exit 3
+fi
+parse_args $OPTS
+
+# Include configs
+. "$CONFIG"
+
+for f in "$CONFIG_PATH"/*.conf; do
+ if [ -f "$f" ]; then
+ . "$f"
+ fi
+done
+
+check_bool $PASSALL
+PASSALL=$?
+check_bool $RECURSIVE
+RECURSIVE=$?
+if [ "$OPT_RECURSIVE" ]; then # -r option overrides RECURSIVE.
+ RECURSIVE=1
+fi
+check_bool $AUTOCOMPILE
+AUTOCOMPILE=$?
+CACHE_PATH="$CACHE_PATH/$KRELEASE"
+
+check_bool $ALLOW_CACHEONLY
+ALLOW_CACHEONLY=$?
+
+__get_all_scripts () {
+ local s
+ if [ $ALLOW_CACHEONLY -eq 1 ]; then
+ for s in "$CACHE_PATH"/*.ko; do
+ if [ -f "$s" ]; then
+ basename "$s" | sed s/\.ko$//g
+ fi
+ done
+ fi
+ for s in "$SCRIPT_PATH"/*.stp; do
+ if [ -f "$s" ]; then
+ basename "$s" | sed s/\.stp$//g
+ fi
+ done
+}
+
+get_all_scripts() {
+ __get_all_scripts | sort | uniq
+}
+
+if [ -z "$OPT_SCRIPTS" ]; then
+ SCRIPTS=`get_all_scripts | xargs`
+ RECURSIVE=1
+else
+ SCRIPTS="$OPT_SCRIPTS"
+fi
+
+#------------------------------------------------------------------
+# Main routine
+#------------------------------------------------------------------
+NR_FAILS=0
+might_fail () { # message exitcode
+ if [ $PASSALL -eq 1 ]; then
+ do_failure "$1"
+ echo
+ [ -z "$2" ] && exit 1
+ exit $2
+ else
+ log "Warning: "$1
+ NR_FAILS=$((NR_FAILS+1))
+ return 0
+ fi
+}
+might_success () { # message
+ if [ $NR_FAILS -ne 0 ]; then
+ log "Warning: $NR_FAILS failure occured."
+ do_warning "$1"
+ else
+ do_success "$1"
+ fi
+ return 0
+}
+
+get_all_runnings () {
+ local f
+ for f in "$STAT_PATH"/*; do
+ if [ -f "$f" ]; then
+ basename "$f"
+ fi
+ done
+}
+
+get_daemon_pid () { # script
+ cat "$STAT_PATH/$1"
+}
+
+check_running () { # script
+ local m f
+ f="$STAT_PATH/$1"
+ m=`$LSMOD | grep "^$1 "`
+ if [ "$m" ]; then
+ [ -f "$f" ] && return 0 # running
+ return 4 # another script is running
+ else
+ [ -f "$f" ] && return 1 # dead, but pidfile remains
+ return 3 # dead
+ fi
+}
+
+# check whether a script cache need to be updated.
+check_cache () { # script opts
+ local s tmp tmp2
+ s=$1; shift 1
+ [ ! -f "$CACHE_PATH/$s.ko" -o ! -f "$CACHE_PATH/$s.opts" ] && return 1
+ if [ $ALLOW_CACHEONLY -ne 1 -o -f "$SCRIPT_PATH/$s.stp" ]; then
+ [ "$SCRIPT_PATH/$s.stp" -nt "$CACHE_PATH/$s.ko" ] && return 2
+ fi
+ tmp=`head -n 1 "$CACHE_PATH/$s.opts"`
+ tmp2=`$UNAME -a`
+ [ "$tmp" != "$tmp2" ] && return 3
+ tmp=`tail -n 1 "$CACHE_PATH/$s.opts"`
+ tmp2="$*"
+ [ "$tmp" != "$tmp2" ] && return 4
+ return 0
+}
+
+stap_getopt () { # opts
+ local ret
+ # TODO: support quoted options
+ getopt -s bash -u \
+ -l 'kelf,kmap::,ignore-vmlinux,ignore-dwarf,vp:' \
+ -o 'hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:F' -- $@
+ ret=$?
+ [ $ret -ne 0 ] && slog "Failed to parse parameters. ($@)"
+ return $ret
+}
+
+get_compile_opts () { # opts
+ local opts o skip
+ opts=`stap_getopt $*`
+ [ $? -ne 0 ] && return 1
+ skip=0
+ for o in $opts; do
+ if [ $skip -ne 0 ]; then skip=0; continue; fi
+ case $o in
+ -p|-m|-r|-c|-x|-e|-s|-o)
+ skip=1 ;;
+ -h|-V|-k)
+ ;;
+ *)
+ echo -n $o" " ;;
+ esac
+ done
+}
+
+get_run_opts () { # normalized_opts
+ local opts o show
+ opts=`stap_getopt $*`
+ [ $? -ne 0 ] && return 1
+ show=0
+ for o in $opts; do
+ case $o in
+ -c|-x|-s|-o)
+ [ $o == '-s' ] && o='-b'
+ echo -n $o" "
+ show=1
+ ;;
+ *)
+ if [ $show -ne 0 ]; then
+ echo -n $o" "
+ show=0
+ fi
+ ;;
+ esac
+ done
+}
+
+prepare_cache_dir () {
+ if [ ! -d "$CACHE_PATH" ]; then
+ logex mkdir -p "$CACHE_PATH"
+ [ $? -ne 0 ] && return 1
+ fi
+ return 0
+}
+
+prepare_stat_dir () {
+ if [ ! -d "$STAT_PATH" ]; then
+ logex mkdir -p "$STAT_PATH"
+ [ $? -ne 0 ] && return 1
+ fi
+ return 0
+}
+
+compile_script () { # script checkcache
+ local opts f tmpdir ret
+ eval f="$SCRIPT_PATH/$1.stp"
+ if [ ! -f "$f" ]; then
+ if [ $ALLOW_CACHEONLY -eq 1 ]; then
+ clog "Warning: no script file($f). Use compiled cache."
+ return 0
+ else
+ clog "Error: no script file($f)."
+ return 1
+ fi
+ fi
+
+ eval opts=\$$1_OPT
+ opts=`get_compile_opts $opts`
+ [ $? -ne 0 ] && return 2
+
+ if [ "$2" = "check" ]; then
+ check_cache $1 $opts
+ [ $? -eq 0 ] && return 0 # already compiled
+ if [ $AUTOCOMPILE -eq 0 ]; then
+ slog "No valid cache for $1"
+ return 1
+ fi
+ fi
+
+ clog " Compiling $1 ... " -n
+ tmpdir=`mktemp -d -p "$TEMP_PATH" cache.XXXXXXXX`
+ if [ $? -ne 0 ]; then
+ clog "failed to create temporary directory."
+ return 1
+ fi
+ pushd "$tmpdir" &> /dev/null
+ logex $STAP -m "$1" -p4 -r $KRELEASE $opts "$f"
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ $UNAME -a > "$1.opts"
+ echo $opts >> "$1.opts"
+ logex mv "$1.ko" "$1.opts" "$CACHE_PATH/"
+ ret=$?
+ else
+ slog "Failed to compile script($1)."
+ fi
+ popd &> /dev/null
+ rm -rf $tmpdir
+ [ $ret -eq 0 ] && clog "done" || clog "error"
+ return $ret
+}
+
+# dependency resolver
+__SORTED=
+__follow_dependency () { # script requesters
+ local opts r reqs s ret
+ s=$1
+ shift 1
+ r=`echo \ $*\ | grep \ $s\ `
+ if [ -n "$r" ]; then
+ might_fail $"Dependency loop detected on $s"
+ return 1
+ fi
+ r=`echo \ $__SORTED\ | grep \ $s\ `
+ [ -n "$r" ] && return 0 # already listed up
+ eval reqs=\$${s}_REQ
+ if [ -n "$reqs" ]; then
+ for r in $reqs; do
+ __follow_dependency $r $s $*
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ return $ret # if one of requires failed, we can't run this script.
+ fi
+ done
+ fi
+ echo -n "$s "
+ return 0
+}
+
+sort_dependency () { # scripts
+ local s r=0
+ __SORTED=
+ for s in $*; do
+ __SORTED="$__SORTED "`__follow_dependency $s`
+ [ $? -ne 0 ] && return 1
+ done
+ echo $__SORTED
+ return 0
+}
+
+start_script () { # script
+ local tmpdir s=$1
+ check_running $s
+ ret=$?
+ [ $ret -eq 0 ] && return 0 # already running
+ if [ $ret -eq 4 ]; then
+ clog "$s is dead, but another script is running."
+ return 4
+ fi
+
+ compile_script $s check
+ ret=$?
+ [ $ret -ne 0 ] && return $ret
+
+ eval opts=\$${s}_OPT
+ opts=`get_run_opts $opts`
+ [ $? -ne 0 ] && return 2
+
+ clog " Starting $1 ... " -n
+ tmpdir=`mktemp -d -p "$TEMP_PATH" cache.XXXXXXXX` # bz7097
+ if [ $? -ne 0 ]; then
+ clog "failed to create temporary directory."
+ return 1
+ fi
+ pushd "$tmpdir" &> /dev/null
+ logex $STAPRUN -L $opts "$CACHE_PATH/$s.ko"
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ # TODO: store daemon pid after supporting on-file flight recorder
+ echo 0 > "$STAT_PATH/$s"
+ fi
+ popd &> /dev/null
+ rm -rf "$tmpdir"
+ [ $ret -eq 0 ] && clog "done" || clog "error"
+ return $ret
+}
+
+start () {
+ local scripts s ret
+ clog $"Starting $prog: " -n
+
+ if [ -n "$DEFAULT_START" -a -z "$OPT_SCRIPTS" ]; then
+ SCRIPTS="$DEFAULT_START"
+ fi
+
+ if [ -z "$SCRIPTS" ]; then
+ do_warning $"no scripts exist."
+ return 5 # program is not installed
+ fi
+
+ prepare_stat_dir
+ if [ $? -ne 0 ]; then
+ do_failure $"Failed to make stat directory ($STAT_PATH)"
+ return 1
+ fi
+ prepare_cache_dir
+ if [ $? -ne 0 ]; then
+ do_failure $"Failed to make cache directory ($CACHE_PATH)"
+ return 1
+ fi
+
+ if [ $RECURSIVE -eq 1 ]; then
+ SCRIPTS=`sort_dependency $SCRIPTS`
+ if [ $? -ne 0 ]; then
+ do_failure $"Failed to sort dependency"
+ return 6 # program is not configured
+ fi
+ fi
+ for s in $SCRIPTS; do
+ start_script "$s"
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ might_fail $"Failed to run \"$s\". ($ret)"
+ fi
+ done
+ might_success $"$prog startup"
+ return 0
+}
+
+stop_script () { # script
+ local p
+ check_running "$1"
+ ret=$?
+ [ $ret -eq 1 ] && rm -f "$STAT_PATH/$1"
+ [ $ret -ne 0 ] && return 0
+
+ p=`get_daemon_pid $1`
+ if [ $p -ne 0 ]; then
+ logex killall -TERM $p
+ else
+ logex $STAPRUN -d "$1"
+ fi
+ [ $? -ne 0 ] && return 1
+ rm -f "$STAT_PATH/$1"
+ return $?
+}
+
+stop () {
+ local s sl=
+ clog $"Stopping $prog: " -n
+ [ -z "$OPT_SCRIPTS" ] && SCRIPTS=`get_all_runnings`
+ if [ $RECURSIVE -eq 1 ]; then
+ SCRIPTS=`sort_dependency $SCRIPTS`
+ if [ $? -ne 0 ]; then
+ do_failure $"Failed to sort dependency"
+ return 6 # program is not configured
+ fi
+ fi
+ for s in $SCRIPTS; do
+ sl="$s $sl"
+ done
+ for s in $sl; do
+ stop_script $s
+ [ $? -ne 0 ] && might_fail $"Failed to run \"$s\". "
+ done
+ might_success $"$prog stopping "
+ return 0
+}
+
+status () {
+ local s pid ret r
+ [ -z "$SCRIPTS" ] && SCRIPTS=`get_all_runnings`
+ ret=3
+ for s in $SCRIPTS; do
+ check_running $s
+ r=$?
+ [ $ret -ne 0 ] && ret=$r
+ case $r in
+ 0)
+ pid=`get_daemon_pid $s`
+ [ $pid -ne 0 ] && pid="($pid)" || pid=
+ echo $"$s$pid is running..." ;;
+ 1|3) echo $"$s is stopped" ;;
+ 4) echo $"$s is dead, but another script is running.";;
+ esac
+ done
+ return $ret
+}
+
+compile () {
+ local s ss
+ clog $"Compiling $prog: " -n
+ prepare_cache_dir
+ if [ $? -ne 0 ]; then
+ do_failure $"Failed to make cache directory ($CACHE_PATH)"
+ return 1
+ fi
+ for s in $SCRIPTS; do
+ ss="$ss "`ls "$CACHE_PATH/$s.ko" "$CACHE_PATH/$s.opts" 2> /dev/null`
+ done
+ ss=`echo -n $ss`
+ if [ "$ss" ]; then
+ clog "Updating caches: $ss"
+ ask_yesno "Do you really want to update above caches"
+ [ $? -eq 0 ] && return 0
+ fi
+ for s in $SCRIPTS; do
+ compile_script $s nocheck
+ [ $? -ne 0 ] && might_fail $"$s compilation failed "
+ done
+ might_success $"$prog compiled "
+ return 0
+}
+
+# Cleanup caches
+cleanup () {
+ local s ss ret
+ clog $"Cleaning up $prog: " -n
+ if [ ! -d "$CACHE_PATH" ]; then
+ do_success "no cache"
+ return 0
+ fi
+
+ for s in $SCRIPTS; do
+ ss="$ss "`ls "$CACHE_PATH/$s.ko" "$CACHE_PATH/$s.opts" 2> /dev/null`
+ done
+ ss=`echo -n $ss`
+ if [ "$ss" ]; then
+ echo "Removing caches: $ss"
+ ask_yesno "Do you really want to remove above caches"
+ [ $? -eq 0 ] && return 0
+ for s in $SCRIPTS; do
+ logex rm -f "$CACHE_PATH/$s.ko" "$CACHE_PATH/$s.opts"
+ [ $? -ne 0 ] && might_fail $"failed to clean cache $s.ko"
+ done
+ might_success "done"
+ return 0
+ fi
+}
+
+RETVAL=0
+
+case $CMD in
+ start)
+ start
+ RETVAL=$?
+ ;;
+ stop)
+ stop
+ RETVAL=$?
+ ;;
+ restart|force-reload)
+ stop
+ start
+ RETVAL=$?
+ ;;
+ status)
+ status
+ RETVAL=$?
+ ;;
+ compile)
+ compile
+ RETVAL=$?
+ ;;
+ cleanup)
+ cleanup
+ RETVAL=$?
+ ;;
+ *)
+ echo_usage
+ RETVAL=3
+ ;;
+esac
+
+echo
+exit $RETVAL
diff --git a/systemtap.spec b/systemtap.spec
index 2586b85a..be00fa98 100644
--- a/systemtap.spec
+++ b/systemtap.spec
@@ -116,6 +116,16 @@ Requires: systemtap
%description sdt-devel
Support tools to allow applications to use static probes.
+%package initscript
+Summary: Systemtap Initscript
+Group: Development/System
+License: GPLv2+
+URL: http://sourceware.org/systemtap/
+Requires: systemtap-runtime, initscripts
+
+%description initscript
+Initscript for Systemtap scripts.
+
%prep
%setup -q %{?setup_elfutils}
@@ -203,6 +213,15 @@ mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/*.pdf docs.installed/
mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/tapsets docs.installed/
%endif
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/init.d/
+install -m 755 initscript/systemtap $RPM_BUILD_ROOT%{_sysconfdir}/init.d/
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/systemtap
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/systemtap/conf.d
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/systemtap/script.d
+install -m 644 initscript/config $RPM_BUILD_ROOT%{_sysconfdir}/systemtap
+mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/cache/systemtap
+mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/systemtap
+
%clean
rm -rf ${RPM_BUILD_ROOT}
@@ -211,6 +230,15 @@ getent group stapdev >/dev/null || groupadd -r stapdev
getent group stapusr >/dev/null || groupadd -r stapusr
exit 0
+%post initscript
+chkconfig --add systemtap
+exit 0
+
+%preun initscript
+chkconfig --del systemtap
+exit 0
+
+
%files
%defattr(-,root,root)
@@ -276,6 +304,18 @@ exit 0
%{_bindir}/dtrace
%{_includedir}/sys/sdt.h
+%files initscript
+%defattr(-,root,root)
+%{_sysconfdir}/init.d/systemtap
+%dir %{_sysconfdir}/systemtap
+%dir %{_sysconfdir}/systemtap/conf.d
+%dir %{_sysconfdir}/systemtap/script.d
+%config(noreplace) %{_sysconfdir}/systemtap/config
+%dir %{_localstatedir}/cache/systemtap
+%dir %{_localstatedir}/run/systemtap
+%doc initscript/README.initscript
+
+
%changelog
* Thu Nov 13 2008 Frank Ch. Eigler <fche@redhat.com> - 0.8-1
- Upstream release.