This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][PATCH] BZ6936 :add systemtap initscript to systemtap source tree


Hi,

Here is a patch which adds systemtap initscript to systemtap src tree.
This patch also adds systemtap-initscript rpm sub-package to systemtap.spec.

This systemtap initscript aims to
- run systemtap script as a service with dependency.
- control(start/stop) those scripts individually.
- launch script before other services.

After installing initscript, you can add your scripts into
/etc/systemtap/script.d/ and specify options by configuration
files under /etc/systemtap/conf.d/.
You can run it by
$ service systemtap start
and stop it by
$ service systemtap stop

See stapasaservice-en.txt in detail.

Thank you,

-- 
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: mhiramat@redhat.com


---
 initscript/config    |   20 +
 initscript/systemtap |  632 +++++++++++++++++++++++++++++++++++++++++++++++++++
 systemtap.spec       |   39 +++
 3 files changed, 691 insertions(+)

Index: systemtap/initscript/systemtap
===================================================================
--- /dev/null
+++ systemtap/initscript/systemtap
@@ -0,0 +1,632 @@
+#!/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=/usr/bin/stap
+STAPRUN=/usr/bin/staprun
+MOD5SUM=/usr/bin/md5sum
+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"
+}
+
+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
+  log "$*"
+  eval $* >> $LOG_FILE 2>&1
+  return $?
+}
+
+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
+}
+
+# Parse arguments
+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
+
+# 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
+}
+
+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
+
+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
+}
+
+# Main routine
+NR_FAILS=0
+
+do_warning () { # message
+  slog "Warning: $1"
+  warning $1
+}
+do_failure () { # message
+  slog "Error: $1"
+  failure $1
+}
+do_success () { # message
+  log "Pass: $1"
+  success $1
+}
+
+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
+  getopt -s bash \
+         -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
+    mkdir -p $CACHE_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
+    [ $ALLOW_CACHEONLY -eq 1 ] && return 0 || return 1
+  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`
+  pushd $tmpdir &> /dev/null
+  log "$STAP -m $1 -p4 -r $KRELEASE $opts $f"
+  eval $STAP -m $1 -p4 -r $KRELEASE $opts $f >> $LOG_FILE 2>&1
+  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\n"
+    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 -ne 3 ] && return $ret
+
+  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
+  pushd $tmpdir &> /dev/null
+  echo $STAPRUN -L $opts $CACHE_PATH/$s.ko >> $LOG_FILE
+  eval $STAPRUN -L $opts $CACHE_PATH/$s.ko >> $LOG_FILE 2>&1
+  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.\n"
+    return 5 # program is not installed
+  fi
+
+  prepare_cache_dir
+  if [ $? -ne 0 ]; then
+    do_failure $"Failed to make cache directory ($CACHE_PATH)\n"
+    return 1
+  fi
+
+  if [ $RECURSIVE -eq 1 ]; then
+    SCRIPTS=`sort_dependency $SCRIPTS`
+    if [ $? -ne 0 ]; then
+      do_failure $"Failed to sort dependency\n"
+      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\". \n"
+    fi
+  done
+  might_success $"$prog startup \n"
+  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 $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\n"
+      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\". \n"
+  done
+  might_success $"$prog stopping \n"
+  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)\n"
+    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
+    echo "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 \n"
+  done
+  might_success $"$prog compiled \n"
+  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: "
+    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\n"
+    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
Index: systemtap/initscript/config
===================================================================
--- /dev/null
+++ systemtap/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=
+
Index: systemtap/systemtap.spec
===================================================================
--- systemtap.orig/systemtap.spec
+++ systemtap/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/system
 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 || group
 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,17 @@ 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
+
+
 %changelog
 * Thu Nov 13 2008 Frank Ch. Eigler <fche@redhat.com> - 0.8-1
 - Upstream release.

Systemtap initscript
Version 0.2
Author: Masami Hiramatsu

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]