1#!/usr/bin/sh 2# 3# statsnoop - snoop file stats as they occur. 4# Written using DTrace (Solaris 10 3/05). 5# 6# $Id: statsnoop 65 2007-10-04 11:09:40Z brendan $ 7# 8# USAGE: statsnoop [-a|-A|-ceghlsvxZ] [-f pathname] [-t syscall] 9# [-n name] [-p PID] 10# 11# statsnoop # default output 12# 13# -a # print most data 14# -A # dump all data, space delimited 15# -c # print cwd of process 16# -e # print errno value 17# -g # print command arguments 18# -l # print syscall type 19# -s # print start time, us 20# -v # print start time, string 21# -x # only print failed stats 22# -Z # print zonename 23# -f pathname # file pathname to snoop 24# -n name # command name to snoop 25# -p PID # process ID to snoop 26# -t syscall # stat syscall to trace 27# eg, 28# statsnoop -v # human readable timestamps 29# statsnoop -S # syscall type 30# statsnoop -e # see error codes 31# statsnoop -f /etc/passwd # snoop this file only 32# 33# FIELDS: 34# ZONE Zone name 35# UID User ID 36# PID Process ID 37# PPID Parent Process ID 38# FD file descriptor (-1 for error) 39# ERR errno value (see /usr/include/sys/errno.h) 40# TYPE syscall type 41# CWD current working directory of process 42# PATH pathname for file stat 43# COMM command name for the process 44# ARGS argument listing for the process 45# TIME timestamp for the stat event, us 46# STRTIME timestamp for the stat event, string 47# 48# SEE ALSO: truss, BSM auditing. 49# 50# COPYRIGHT: Copyright (c) 2007 Brendan Gregg. 51# 52# CDDL HEADER START 53# 54# The contents of this file are subject to the terms of the 55# Common Development and Distribution License, Version 1.0 only 56# (the "License"). You may not use this file except in compliance 57# with the License. 58# 59# You can obtain a copy of the license at Docs/cddl1.txt 60# or http://www.opensolaris.org/os/licensing. 61# See the License for the specific language governing permissions 62# and limitations under the License. 63# 64# CDDL HEADER END 65# 66# Author: Brendan Gregg [Sydney, Australia] 67# 68# 09-Sep-2007 Brendan Gregg Created this. 69# 70 71 72############################## 73# --- Process Arguments --- 74# 75 76### Default variables 77opt_dump=0; opt_file=0; opt_time=0; opt_timestr=0; opt_args=0 78opt_zone=0; opt_cwd=0; opt_failonly=0; opt_err=0; filter=0; pathname=. 79opt_name=0; opt_pid=0; opt_type=0; opt_trace=0; pname=.; pid=0; trace=. 80 81### Process options 82while getopts aAcef:ghln:p:st:vxZ name 83do 84 case $name in 85 a) opt_time=1; opt_timestr=1; opt_args=1; opt_err=1 ;; 86 A) opt_dump=1 ;; 87 c) opt_cwd=1 ;; 88 e) opt_err=1 ;; 89 g) opt_args=1 ;; 90 f) opt_file=1; pathname=$OPTARG ;; 91 l) opt_type=1 ;; 92 n) opt_name=1; pname=$OPTARG ;; 93 p) opt_pid=1; pid=$OPTARG ;; 94 s) opt_time=1 ;; 95 t) opt_trace=1; trace=$OPTARG ;; 96 v) opt_timestr=1 ;; 97 x) opt_failonly=1 ;; 98 Z) opt_zone=1 ;; 99 h|?) cat <<-END >&2 100 USAGE: statsnoop [-a|-A|-ceghlsvxZ] [-f pathname] [-t syscall] 101 [-n execname] [-p PID] 102 statsnoop # default output 103 -a # print most data 104 -A # dump all data, space delimited 105 -c # print cwd of process 106 -e # print errno value 107 -g # print command arguments 108 -l # print syscall type 109 -s # print start time, us 110 -v # print start time, string 111 -x # only print failed stats 112 -Z # print zonename 113 -f pathname # pathname name to snoop 114 -n name # process name to snoop 115 -p PID # process ID to snoop 116 -t syscall # stat syscall to trace 117 eg, 118 statsnoop -v # human readable timestamps 119 statsnoop -e # see error codes 120 statsnoop -f /etc/motd # snoop this file only 121 END 122 exit 1 123 esac 124done 125 126### Option logic 127if [ $opt_dump -eq 1 ]; then 128 opt_zone=0; opt_cwd=0; opt_time=0; opt_timestr=0; opt_type=0 129 opt_args=2 130fi 131if [ $opt_name -eq 1 -o $opt_pid -eq 1 -o $opt_trace -eq 1 ]; then 132 filter=1 133fi 134 135 136################################# 137# --- Main Program, DTrace --- 138# 139/usr/sbin/dtrace -n ' 140 /* 141 * Command line arguments 142 */ 143 inline int OPT_dump = '$opt_dump'; 144 inline int OPT_file = '$opt_file'; 145 inline int OPT_args = '$opt_args'; 146 inline int OPT_cwd = '$opt_cwd'; 147 inline int OPT_err = '$opt_err'; 148 inline int OPT_zone = '$opt_zone'; 149 inline int OPT_time = '$opt_time'; 150 inline int OPT_timestr = '$opt_timestr'; 151 inline int OPT_type = '$opt_type'; 152 inline int OPT_failonly = '$opt_failonly'; 153 inline int OPT_pid = '$opt_pid'; 154 inline int OPT_name = '$opt_name'; 155 inline int OPT_trace = '$opt_trace'; 156 inline int FILTER = '$filter'; 157 inline int PID = '$pid'; 158 inline string PATHNAME = "'$pathname'"; 159 inline string NAME = "'$pname'"; 160 inline string TRACE = "'$trace'"; 161 162 #pragma D option quiet 163 #pragma D option switchrate=10hz 164 165 /* 166 * Print header 167 */ 168 dtrace:::BEGIN 169 { 170 /* print optional headers */ 171 OPT_time ? printf("%-14s ", "TIME") : 1; 172 OPT_timestr ? printf("%-20s ", "STRTIME") : 1; 173 OPT_zone ? printf("%-10s ", "ZONE") : 1; 174 175 /* print dump headers */ 176 OPT_dump ? printf("%s %s %s %s %s %s %s %s %s %s %s", "ZONE", 177 "TIME", "UID", "PID", "PPID", "COMM", "FD", "ERR", "CWD", 178 "PATH", "ARGS") : printf("%5s %6s ","UID","PID"); 179 180 /* print main headers */ 181 OPT_args == 0 ? printf("%-12s ", "COMM") : 1; 182 OPT_dump == 0 ? printf("%3s ", "FD") : 1; 183 OPT_err ? printf("%3s ", "ERR") : 1; 184 OPT_cwd ? printf("%-20s ", "CWD") : 1; 185 OPT_type ? printf("%-8s ", "TYPE") : 1; 186 OPT_dump == 0 ? printf("%-20s ", "PATH") : 1; 187 OPT_args == 1 ? printf("%s", "ARGS") : 1; 188 printf("\n"); 189 } 190 191 /* 192 * Print stat event 193 */ 194 syscall::stat:entry, syscall::stat64:entry, syscall::xstat:entry, 195 syscall::lstat:entry, syscall::lstat64:entry, syscall::lxstat:entry, 196 syscall::fstat:entry, syscall::fstat64:entry, syscall::fxstat:entry 197 { 198 /* default is to trace unless filtering */ 199 self->ok = FILTER ? 0 : 1; 200 201 /* check each filter */ 202 (OPT_name == 1 && NAME == execname) ? self->ok = 1 : 1; 203 (OPT_pid == 1 && PID == pid) ? self->ok = 1 : 1; 204 (OPT_trace == 1 && TRACE == probefunc) ? self->ok = 1 : 1; 205 } 206 207 syscall::stat:entry, syscall::stat64:entry, 208 syscall::lstat:entry, syscall::lstat64:entry, syscall::lxstat:entry 209 /self->ok/ 210 { 211 self->pathp = arg0; 212 } 213 214 syscall::xstat:entry 215 /self->ok/ 216 { 217 self->pathp = arg1; 218 } 219 220 syscall::stat:return, syscall::stat64:return, syscall::xstat:return, 221 syscall::lstat:return, syscall::lstat64:return, syscall::lxstat:return 222 /self->ok/ 223 { 224 self->path = copyinstr(self->pathp); 225 self->pathp = 0; 226 } 227 228 syscall::fstat:return, syscall::fstat64:entry, syscall::fxstat:entry 229 /self->ok/ 230 { 231 self->filep = curthread->t_procp->p_user.u_finfo.fi_list[arg0].uf_file; 232 } 233 234 syscall::fstat:return, syscall::fstat64:return, syscall::fxstat:return 235 /self->ok/ 236 { 237 this->vnodep = self->filep != 0 ? self->filep->f_vnode : 0; 238 self->path = this->vnodep ? (this->vnodep->v_path != 0 ? 239 cleanpath(this->vnodep->v_path) : "<unknown>") : "<unknown>"; 240 self->filep = 0; 241 } 242 243 syscall::stat:return, syscall::stat64:return, syscall::xstat:return, 244 syscall::lstat:return, syscall::lstat64:return, syscall::lxstat:return, 245 syscall::fstat:return, syscall::fstat64:return, syscall::fxstat:return 246 /self->ok && (! OPT_failonly || (int)arg0 < 0) && 247 ((OPT_file == 0) || (OPT_file == 1 && PATHNAME == copyinstr(self->pathp)))/ 248 { 249 /* print optional fields */ 250 OPT_time ? printf("%-14d ", timestamp/1000) : 1; 251 OPT_timestr ? printf("%-20Y ", walltimestamp) : 1; 252 OPT_zone ? printf("%-10s ", zonename) : 1; 253 254 /* print dump fields */ 255 OPT_dump ? printf("%s %d %d %d %d %s %d %d %s %s %S", zonename, 256 timestamp/1000, uid, pid, ppid, execname, (int)arg0, errno, 257 cwd, self->path, curpsinfo->pr_psargs) : 258 printf("%5d %6d ", uid, pid); 259 260 /* print main fields */ 261 OPT_args == 0 ? printf("%-12.12s ", execname) : 1; 262 OPT_dump == 0 ? printf("%3d ", (int)arg0) : 1; 263 OPT_err ? printf("%3d ", errno) : 1; 264 OPT_cwd ? printf("%-20s ", cwd) : 1; 265 OPT_type ? printf("%-8s ", probefunc) : 1; 266 OPT_dump == 0 ? printf("%-20s ", self->path) : 1; 267 OPT_args == 1 ? printf("%S", curpsinfo->pr_psargs) : 1; 268 printf("\n"); 269 270 /* cleanup */ 271 self->path = 0; 272 self->ok = 0; 273 } 274 275 /* 276 * Cleanup 277 */ 278 syscall::stat:return, syscall::stat64:return, syscall::xstat:return, 279 syscall::lstat:return, syscall::lstat64:return, syscall::lxstat:return, 280 syscall::fstat:return, syscall::fstat64:return, syscall::fxstat:return 281 /self->ok/ 282 { 283 self->path = 0; 284 self->ok = 0; 285 } 286' 287