Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/dwatch/dwatch
- This file was added.
Property | Old Value | New Value |
---|---|---|
svn:executable | null | * \ No newline at end of property |
svn:keywords | null | FreeBSD=%H \ No newline at end of property |
#!/bin/sh | |||||
#- | |||||
# Copyright (c) 2014-2017 Devin Teske | |||||
# All rights reserved. | |||||
# | |||||
# Redistribution and use in source and binary forms, with or without | |||||
# modification, are permitted provided that the following conditions | |||||
# are met: | |||||
# 1. Redistributions of source code must retain the above copyright | |||||
# notice, this list of conditions and the following disclaimer. | |||||
# 2. Redistributions in binary form must reproduce the above copyright | |||||
# notice, this list of conditions and the following disclaimer in the | |||||
# documentation and/or other materials provided with the distribution. | |||||
# | |||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
# SUCH DAMAGE. | |||||
# | |||||
############################################################ IDENT(1) | |||||
# | |||||
# $Title: Watch processes as they enter a particular DTrace probe $ | |||||
# $FreeBSD$ | |||||
# | |||||
############################################################ CONFIGURATION | |||||
# | |||||
# DTrace pragma settings | |||||
# | |||||
DTRACE_PRAGMA=" | |||||
option quiet | |||||
option dynvarsize=16m | |||||
option switchrate=10hz | |||||
" # END-QUOTE | |||||
# | |||||
# Modules | |||||
# | |||||
: ${DWATCH_MODULES_PATH="/usr/libexec/dwatch:/usr/local/libexec/dwatch"} | |||||
############################################################ GLOBALS | |||||
pgm="${0##*/}" # Program basename | |||||
# | |||||
# Command-line arguments | |||||
# | |||||
PROBE= | |||||
MODULE= | |||||
# | |||||
# Command-line options | |||||
# | |||||
COUNT=0 # -c count | |||||
DEBUG= # -d | |||||
EVENT_CODE= # -e code | |||||
FILTER= # -f regex | |||||
GROUP= # -g group | |||||
LIST= # -l | |||||
MAX_ARGS=64 # -m num | |||||
MAX_DEPTH=64 # -n num | |||||
QUIET= # -q | |||||
USER= # -u user | |||||
VERBOSE= # -v | |||||
# | |||||
# Global exit status | |||||
# | |||||
SUCCESS=0 | |||||
FAILURE=1 | |||||
# | |||||
# Miscellaneous | |||||
# | |||||
ACTIONS= | |||||
DEFAULT_EVENT_TAG='printf("%d.%d %s[%d]: ", | |||||
this->uid0, this->gid0, execname, this->pid0);' | |||||
DETAILS= | |||||
EVENT_TAG= | |||||
ID=2 | |||||
PRINT=entry | |||||
RGID= | |||||
RUID= | |||||
SUDO= | |||||
export SUDO_PROMPT="[sudo] Password:" | |||||
############################################################ FUNCTIONS | |||||
usage() | |||||
{ | |||||
local optfmt="\t%-9s %s\n" | |||||
exec >&2 | |||||
[ "$*" ] && printf "%s: %s\n" "$pgm" "$*" | |||||
printf "Usage: %s [OPTIONS] probe | module\n" "$pgm" | |||||
printf " %s [OPTIONS] -l [pattern]\n" "$pgm" | |||||
printf "OPTIONS:\n" | |||||
printf "$optfmt" "-c count" \ | |||||
"Exit after count matching entries (Default 0 for disabled)." | |||||
printf "$optfmt" "-d" \ | |||||
"Debug. Send dtrace(1) script to stdout instead of executing." | |||||
printf "$optfmt" "-e code" \ | |||||
"DTrace code for event details. If \`-', read from stdin." | |||||
printf "$optfmt" "-f regex" \ | |||||
"Filter. Only show blocks matching awk(1) regular expression." | |||||
printf "$optfmt" "-g group" \ | |||||
"Group filter. Only show processes matching group name/gid." | |||||
printf "$optfmt" "-h" \ | |||||
"Help. Display syntax and available modules then exit." | |||||
printf "$optfmt" "-l" \ | |||||
"List available probe points on standard output and exit." | |||||
printf "$optfmt" "-M" \ | |||||
"Disable modules. Same as setting DWATCH_MODULES_PATH to NULL." | |||||
printf "$optfmt" "-m num" \ | |||||
"Maximum number of arguments to display (Default $MAX_ARGS)." | |||||
printf "$optfmt" "-n num" \ | |||||
"Maximum directory depth to display (Default $MAX_DEPTH)." | |||||
printf "$optfmt" "-q" \ | |||||
"Quiet. Disable informational messages displayed on stderr." | |||||
printf "$optfmt" "-u user" \ | |||||
"User filter. Only show processes matching user name/uid." | |||||
printf "$optfmt" "-v" \ | |||||
"Verbose. Show parent, grandparent, and ancestor of process." | |||||
# Build a list of modules available | |||||
local modules | |||||
modules=$( { IFS=: | |||||
for dir in $DWATCH_MODULES_PATH; do | |||||
[ -d "$dir" ] || continue | |||||
for path in $dir/*; do | |||||
[ -f "$path" ] || continue | |||||
name="${path##*/}" | |||||
[ "$name" = "${name%%[!0-9A-Za-z_]*}" ] || | |||||
continue | |||||
echo $name | |||||
done | |||||
done | |||||
} | sort -u ) | |||||
# Get the longest module name | |||||
local longest_module_name | |||||
longest_module_name=$( echo "$modules" | | |||||
awk -v N=0 '(L = length($0)) > N { N = L } END { print N }' ) | |||||
# Get the width of the terminal | |||||
local max_size="$( stty size 2> /dev/null )" | |||||
: ${max_size:=24 80} | |||||
local max_width="${max_size#*[$IFS]}" | |||||
# Determine how many columns we can display | |||||
local x=$longest_module_name ncols=1 | |||||
x=$(( $x + 8 )) # Accommodate leading tab character | |||||
x=$(( $x + 3 + $longest_module_name )) # Preload end of next column | |||||
while [ $x -lt $max_width ]; do | |||||
ncols=$(( $ncols + 1 )) | |||||
x=$(( $x + 3 + $longest_module_name )) | |||||
done | |||||
printf "MODULES:\n" | |||||
echo "$modules" | | |||||
awk -v ncols=$ncols -v colsize=$longest_module_name ' | |||||
BEGIN { row_item[1] = "" } | |||||
function print_row() | |||||
{ | |||||
printf "\t%-*s", colsize, row_item[1] | |||||
for (i = 2; i <= cur_col; i++) | |||||
printf " %-*s", colsize, row_item[i] | |||||
printf "\n" | |||||
} | |||||
{ | |||||
n++ | |||||
cur_col = (( n - 1 ) % ncols ) + 1 | |||||
row_item[cur_col] = $0 | |||||
if ( cur_col == ncols ) print_row() | |||||
} | |||||
END { if (cur_col < ncols) print_row() }' | |||||
exit $FAILURE | |||||
} | |||||
pproc() | |||||
{ | |||||
local proc="curthread->td_proc" | |||||
[ $1 -gt 0 ] && proc="this->proc->p_pptr" | |||||
awk 'NR > 1 && $0 { $0 = "\t" $0 } 1' <<-EOFPREAMBLE | |||||
this->proc = $proc; | |||||
this->pid$1 = this->proc->p_pid; | |||||
this->uid$1 = this->proc->p_ucred->cr_uid; | |||||
this->gid$1 = this->proc->p_ucred->cr_rgid; | |||||
this->p_args = this->proc ? this->proc->p_args : 0; | |||||
this->ar_length = this->p_args ? this->p_args->ar_length : 0; | |||||
this->ar_args = (char *)(this->p_args ? this->p_args->ar_args : 0); | |||||
this->arg${1}_0 = this->ar_length > 0 ? | |||||
this->ar_args : stringof(this->proc->p_comm); | |||||
this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0; | |||||
this->ar_args += this->len; | |||||
this->ar_length -= this->len; | |||||
EOFPREAMBLE | |||||
awk -v P=$1 -v MAX_ARGS=$MAX_ARGS ' | |||||
$0 { $0 = "\t" $0 } | |||||
buf = buf $0 "\n" { } | |||||
END { | |||||
while (++N <= MAX_ARGS) { | |||||
$0 = buf | |||||
gsub(/P/, P) | |||||
gsub(/N/, N) | |||||
sub(/\n$/, "") | |||||
} | |||||
} | |||||
' <<-EOFARGS | |||||
this->argP_N = this->ar_length > 0 ? this->ar_args : ""; | |||||
this->len = this->ar_length > 0 ? strlen(this->ar_args) + 1 : 0; | |||||
this->ar_args += this->len; | |||||
this->ar_length -= this->len; | |||||
EOFARGS | |||||
awk '$0 = "\t" $0' <<-EOFPROC | |||||
this->arg${1}_$(( $MAX_ARGS + 1 )) = this->ar_length > 0 ? "..." : ""; | |||||
EOFPROC | |||||
} | |||||
pproc_dump() | |||||
{ | |||||
local OPTIND=1 OPTARG flag | |||||
local nl=1 verbose= | |||||
while getopts nv flag; do | |||||
case "$flag" in | |||||
n) nl= ;; | |||||
v) verbose=1 ;; | |||||
esac | |||||
done | |||||
shift $(( $OPTIND - 1 )) | |||||
[ "$verbose" ] && awk -v P=$1 ' | |||||
$0 { $0 = "\t" $0 } | |||||
buf = buf $0 "\n" { } | |||||
END { | |||||
$0 = buf | |||||
gsub(/S/, P < 3 ? sprintf("%" 7-2*(P+1) "s", "") : "") | |||||
gsub(/B/, P < 3 ? "\\" : "") | |||||
} | |||||
' <<-EOFPREAMBLE | |||||
printf(" SB-+= %05d %d.%d %s", | |||||
this->pid$1, this->uid$1, this->gid$1, this->arg${1}_0); | |||||
EOFPREAMBLE | |||||
awk -v P=$1 -v MAX_ARGS=$MAX_ARGS ' | |||||
$0 { $0 = "\t" $0 } | |||||
buf = buf $0 "\n" { } | |||||
END { | |||||
while (++N <= MAX_ARGS) { | |||||
$0 = buf | |||||
if (N == 1) sub(/^\t/, "") | |||||
gsub(/P/, P) | |||||
gsub(/N/, N) | |||||
sub(/\n$/, "") | |||||
} | |||||
} | |||||
' <<-EOFARGS | |||||
printf("%s%s", this->argP_N != "" ? " " : "", this->argP_N); | |||||
EOFARGS | |||||
if [ "$nl" ]; then | |||||
awk '$0 = "\t" $0' <<-EOFTAIL | |||||
printf("%s", this->arg${1}_0 != "" ? "\\n" : ""); | |||||
EOFTAIL | |||||
fi | |||||
} | |||||
############################################################ MAIN | |||||
# | |||||
# Process command-line options | |||||
# | |||||
while getopts c:de:f:g:hlMm:n:qu:v flag; do | |||||
case "$flag" in | |||||
c) COUNT="$OPTARG" ;; | |||||
d) DEBUG=1 ;; | |||||
e) EVENT_CODE=1 DETAILS="$OPTARG" ;; | |||||
f) FILTER="$OPTARG" ;; | |||||
g) GROUP="$OPTARG" ;; | |||||
h) usage ;; # NOTREACHED | |||||
l) LIST=1 ;; | |||||
M) DWATCH_MODULES_PATH= ;; | |||||
m) MAX_ARGS="$OPTARG" ;; | |||||
n) MAX_DEPTH="$OPTARG" ;; | |||||
q) QUIET=1 ;; | |||||
u) USER="$OPTARG" ;; | |||||
v) VERBOSE=1 ;; | |||||
*) usage # NOTREACHED | |||||
esac | |||||
done | |||||
shift $(( $OPTIND - 1 )) | |||||
# If we're running as root, no need for sudo(8) | |||||
[ "$( id -u )" != 0 ] && type sudo > /dev/null 2>&1 && SUDO=sudo | |||||
# | |||||
# Read event code from stdin if `-' is the argument to `-e code' option | |||||
# | |||||
[ "$EVENT_CODE" -a "$DETAILS" = "-" ] && DETAILS=$( cat ) | |||||
# | |||||
# List probes if `-l' was given | |||||
# | |||||
if [ "$LIST" ]; then | |||||
$SUDO dtrace -l | awk -v pattern="$1" '$NF == "entry" && | |||||
!_[$0 = $2 ":" (NF > 4 ? $3 : "") ":" $--NF]++ && | |||||
$0 ~ pattern' | |||||
exit | |||||
fi | |||||
# | |||||
# Validate number of arguments | |||||
# | |||||
[ $# -gt 0 ] || usage "missing probe/module argument" # NOTREACHED | |||||
# | |||||
# Validate `-c count' option argument | |||||
# | |||||
case "$COUNT" in | |||||
"") usage "-c option requires a number argument" ;; # NOTREACHED | |||||
*[!0-9]*) usage "-c argument must be a number" ;; # NOTREACHED | |||||
esac | |||||
# | |||||
# Validate `-g group' option argument | |||||
# | |||||
case "$GROUP" in | |||||
"") : fall through ;; | |||||
*[!0-9]*) | |||||
if ! RGID=$( getent group | | |||||
awk -F: -v group="$GROUP" '$1 == group { print $3 }' ) | |||||
then | |||||
echo "$pgm: No such group: $GROUP" >&2 | |||||
exit $FAILURE | |||||
fi | |||||
;; | |||||
*) RGID=$GROUP | |||||
esac | |||||
# | |||||
# Validate `-m num' option argument | |||||
# | |||||
case "$MAX_ARGS" in | |||||
"") usage "-m option requires a number argument" ;; # NOTREACHED | |||||
*[!0-9]*) usage "-m argument must be a number" ;; # NOTREACHED | |||||
esac | |||||
# | |||||
# Validate `-n num' option argument | |||||
# | |||||
case "$MAX_DEPTH" in | |||||
"") usage "-n option requires a number argument" ;; # NOTREACHED | |||||
*[!0-9]*) usage "-n argument must be a number" ;; # NOTREACHED | |||||
esac | |||||
# | |||||
# Validate `-u user' option argument | |||||
# | |||||
case "$USER" in | |||||
"") : fall through ;; | |||||
*[!0-9]*) | |||||
if ! RUID=$( id -u "$USER" ); then | |||||
echo "$pgm: No such user: $USER" >&2 | |||||
exit $FAILURE | |||||
fi | |||||
;; | |||||
*) RUID=$USER | |||||
esac | |||||
# | |||||
# Load kernel module(s) if necessary | |||||
# | |||||
if type kldstat > /dev/null 2>&1; then | |||||
kldstat -qm dtrace || $SUDO kldload dtraceall || exit | |||||
fi | |||||
# | |||||
# If argument is not fully qualified probe (e.g., one that contains ":"), check | |||||
# for a module by that name, otherwise try to expand the probe name. | |||||
# | |||||
PROBE="$1" | |||||
case "$PROBE" in | |||||
*[![:alnum:]_]*) : fall through ;; | |||||
*) | |||||
found=1 | |||||
oldIFS="$IFS" IFS=: | |||||
for dir in $DWATCH_MODULES_PATH; do | |||||
[ -d "$dir" ] || continue | |||||
[ -f "$dir/$PROBE" ] || continue | |||||
MODULE="$PROBE" found=1 | |||||
unset EVENT_TAG | |||||
. "$dir/$MODULE" | |||||
: ${PROBE:=$MODULE} | |||||
: ${ID:=2} | |||||
: ${PRINT:=entry} | |||||
: ${EVENT_TAG=$DEFAULT_EVENT_TAG} | |||||
break | |||||
done | |||||
IFS="$oldIFS" | |||||
# A loaded module may have left PROBE unqualified | |||||
case "$PROBE" in | |||||
*[![:alnum:]_]*) : fall through ;; | |||||
*) | |||||
P=$( $SUDO dtrace -ln "$PROBE:entry" | awk ' | |||||
$NF == "entry" { print $2 "::" $(NF-1); exit found++ } | |||||
END { exit !found } | |||||
' ) && PROBE="$P" | |||||
esac | |||||
esac | |||||
# | |||||
# Header for watched probe entry | |||||
# | |||||
[ "$MODULE" ] || case "$PROBE" in | |||||
*:execve) | |||||
PRINT="return /execname != this->caller_execname/" | |||||
EVENT_TAG='printf("%d.%d %s[%d]: ", | |||||
this->uid1, this->gid1, this->caller_execname, this->pid1);' | |||||
;; | |||||
*) | |||||
EVENT_TAG="$DEFAULT_EVENT_TAG" | |||||
esac | |||||
# | |||||
# Event details | |||||
# | |||||
[ "$MODULE" -o "$EVENT_CODE" ] || DETAILS=" | |||||
printf(\"%s\", this->arg0_0); | |||||
$( pproc_dump -n 0 ) | |||||
" # END-QUOTE | |||||
# | |||||
# DTrace script | |||||
# | |||||
# If `-d' is given, script is sent to stdout for debugging | |||||
# If `-c count", `-f regex', `-g group', or `-u user' is given, run script with | |||||
# dtrace and send output to awk(1) post-processor (making sure to preserve the | |||||
# exit code returned by dtrace invocation). Otherwise, simply run script with | |||||
# dtrace and then exit. | |||||
# | |||||
{ | |||||
if [ "$DEBUG" ]; then | |||||
# Send script to stdout | |||||
cat | |||||
exit | |||||
fi | |||||
if ! [ "$FILTER" -o "$COUNT" != 0 -o "$USER" -o "$GROUP" ]; then | |||||
# Run script without filter | |||||
$SUDO dtrace -s /dev/stdin | |||||
exit | |||||
fi | |||||
if [ ! "$QUIET" ]; then | |||||
msg="dtrace:" | |||||
[ "$COUNT" ] && msg="$msg count: $COUNT" | |||||
[ "$FILTER" ] && msg="$msg filter: $FILTER" | |||||
[ "$GROUP" ] && msg="$msg group: $GROUP" | |||||
[ "$USER" ] && msg="$msg user: $USER" | |||||
echo "$msg" >&2 | |||||
fi | |||||
# Send script output to post-processor for filtering | |||||
exec 3>&1 | |||||
exec 4>&2 | |||||
status=$( exec 5>&1; ( | |||||
trap 'echo $? >&5' EXIT | |||||
( trap exit INT; $SUDO dtrace -s /dev/stdin ) & | |||||
echo $! | |||||
) 2>&4 | awk \ | |||||
-v count="$COUNT" \ | |||||
-v filter="$FILTER" \ | |||||
-v gid=$RGID \ | |||||
-v uid=$RUID \ | |||||
-v verbose=$VERBOSE \ | |||||
' # Start awk(1) post-processor | |||||
############################################# BEGIN | |||||
BEGIN { | |||||
getline dtrace | |||||
pid = num = "[[:digit:]]+" | |||||
fmt = "(\n%6s\\\\-\\+= %s|^[^\n]*) %s\\.%s [^\n]*$" | |||||
uidfilter = sprintf(fmt, "", pid, uid, num) | |||||
gidfilter = sprintf(fmt, "", pid, num, gid) | |||||
} | |||||
############################################# FUNCTIONS | |||||
function dump() { | |||||
lines = block | |||||
block = "" | |||||
if (uid && lines !~ uidfilter) return | |||||
if (gid && lines !~ gidfilter) return | |||||
if (filter && lines !~ filter) return | |||||
if (lines) print lines | |||||
++matches | |||||
} | |||||
############################################# MAIN | |||||
{ block = (block ? block "\n" : block) $0 } | |||||
!verbose { dump() } | |||||
$0 ~ sprintf("^%6s\\\\-\\+= %s ", "", pid) { dump() } | |||||
count && matches >= count { exit } | |||||
############################################# END | |||||
END { dump(); system(sprintf("kill %s", dtrace)) } | |||||
' >&3 ) | |||||
exit $status | |||||
} <<EOF | |||||
#!/usr/sbin/dtrace -s | |||||
/* - | |||||
* Copyright (c) 2014-2017 Devin Teske <dteske@FreeBSD.org> | |||||
* All rights reserved. | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS \`\`AS IS'' AND | |||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
* | |||||
* \$Title: dtrace(1) script to log process(es) entering $PROBE $ | |||||
* \$FreeBSD$ | |||||
*/ | |||||
$( echo "$DTRACE_PRAGMA" | awk ' | |||||
!/^[[:space:]]*(#|$)/, sub(/^[[:space:]]*/, "#pragma D ")||1 | |||||
' ) | |||||
/*********************************************************/ | |||||
syscall::execve:entry /* probe ID 1 */ | |||||
{ | |||||
this->caller_execname = execname; | |||||
} | |||||
${ACTIONS:+ | |||||
/*********************************************************/ | |||||
$ACTIONS} | |||||
/*********************************************************/ | |||||
$PROBE:$PRINT /* probe ID $ID */ | |||||
{ | |||||
/* | |||||
* Examine process, parent process, and grandparent process details | |||||
*/ | |||||
/******************* CURPROC *******************/ | |||||
$( pproc 0 ) | |||||
/******************* PPARENT *******************/ | |||||
$( if [ "$VERBOSE" ]; then pproc 1; else echo " | |||||
this->proc = this->proc->p_pptr; | |||||
this->pid1 = this->proc->p_pid; | |||||
this->uid1 = this->proc->p_ucred->cr_uid; | |||||
this->gid1 = this->proc->p_ucred->cr_rgid; | |||||
"; fi ) | |||||
/******************* GPARENT *******************/ | |||||
$( [ "$VERBOSE" ] && pproc 2 ) | |||||
/******************* APARENT *******************/ | |||||
$( [ "$VERBOSE" ] && pproc 3 ) | |||||
/***********************************************/ | |||||
/* | |||||
* Print process, parent, grandparent, and ancestor details | |||||
*/ | |||||
printf("%Y ", timestamp + 1468045731600000000); | |||||
$EVENT_TAG | |||||
$DETAILS | |||||
printf("\\n"); | |||||
$( if [ "$VERBOSE" ]; then | |||||
pproc_dump -v 3 | |||||
pproc_dump -v 2 | |||||
pproc_dump -v 1 | |||||
pproc_dump -v 0 | |||||
fi ) | |||||
} | |||||
EOF | |||||
################################################################################ | |||||
# END | |||||
################################################################################ |