opensnoop revision 235454
1#!/bin/sh 2# 3# opensnoop - snoop file opens as they occur. 4# Written using DTrace (Solaris 10 3/05). 5# 6# $Id: opensnoop 3 2007-08-01 10:50:08Z brendan $ 7# 8# USAGE: opensnoop [-a|-A|-ceghsvxZ] [-f pathname] [-n name] [-p PID] 9# 10# opensnoop # default output 11# 12# -a # print most data 13# -A # dump all data, space delimited 14# -c # print cwd of process 15# -e # print errno value 16# -g # print command arguments 17# -s # print start time, us 18# -v # print start time, string 19# -x # only print failed opens 20# -Z # print zonename 21# -f pathname # file pathname to snoop 22# -n name # command name to snoop 23# -p PID # process ID to snoop 24# eg, 25# opensnoop -v # human readable timestamps 26# opensnoop -e # see error codes 27# opensnoop -f /etc/passwd # snoop this file only 28# 29# FIELDS: 30# ZONE Zone name 31# UID User ID 32# PID Process ID 33# PPID Parent Process ID 34# FD file descriptor (-1 for error) 35# ERR errno value (see /usr/include/sys/errno.h) 36# CWD print current working directory of process 37# PATH pathname for file open 38# COMM command name for the process 39# ARGS argument listing for the process 40# TIME timestamp for the open event, us 41# STRTIME timestamp for the open event, string 42# 43# SEE ALSO: truss, BSM auditing. 44# 45# COPYRIGHT: Copyright (c) 2006 Brendan Gregg. 46# 47# CDDL HEADER START 48# 49# The contents of this file are subject to the terms of the 50# Common Development and Distribution License, Version 1.0 only 51# (the "License"). You may not use this file except in compliance 52# with the License. 53# 54# You can obtain a copy of the license at Docs/cddl1.txt 55# or http://www.opensolaris.org/os/licensing. 56# See the License for the specific language governing permissions 57# and limitations under the License. 58# 59# CDDL HEADER END 60# 61# Author: Brendan Gregg [Sydney, Australia] 62# 63# 09-May-2004 Brendan Gregg Created this. 64# 21-Jan-2005 " " Wrapped in sh to provide options. 65# 08-May-2005 " " Rewritten for performance. 66# 14-May-2005 " " Added errno. 67# 28-Jun-2005 " " Added cwd, zonename. 68# 17-Sep-2005 " " Increased switchrate, fixed page fault bug. 69# 16-Jan-2006 " " Added -n, -p. 70# 16-Jan-2006 " " Last update. 71# 72 73 74############################## 75# --- Process Arguments --- 76# 77 78### Default variables 79opt_dump=0; opt_file=0; opt_time=0; opt_timestr=0; opt_args=0 80opt_zone=0; opt_cwd=0; opt_failonly=0; opt_err=0; filter=0; pathname=. 81opt_name=0; opt_pid=0; pname=.; pid=0 82 83### Process options 84while getopts aAcef:ghn:p:svxZ name 85do 86 case $name in 87 a) opt_time=1; opt_timestr=1; opt_args=1; opt_err=1 ;; 88 A) opt_dump=1 ;; 89 c) opt_cwd=1 ;; 90 e) opt_err=1 ;; 91 g) opt_args=1 ;; 92 f) opt_file=1; pathname=$OPTARG ;; 93 n) opt_name=1; pname=$OPTARG ;; 94 p) opt_pid=1; pid=$OPTARG ;; 95 s) opt_time=1 ;; 96 v) opt_timestr=1 ;; 97 x) opt_failonly=1 ;; 98 Z) opt_zone=1 ;; 99 h|?) cat <<-END >&2 100 USAGE: opensnoop [-a|-A|-ceghsvxZ] [-f pathname] 101 [-n name] [-p PID] 102 opensnoop # 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 -s # print start time, us 109 -v # print start time, string 110 -x # only print failed opens 111 -Z # print zonename 112 -f pathname # pathname name to snoop 113 -n name # process name to snoop 114 -p PID # process ID to snoop 115 eg, 116 opensnoop -v # human readable timestamps 117 opensnoop -e # see error codes 118 opensnoop -f /etc/motd # snoop this file only 119 END 120 exit 1 121 esac 122done 123 124### Option logic 125if [ $opt_dump -eq 1 ]; then 126 opt_zone=0; opt_cwd=0; opt_time=0; opt_timestr=0; opt_args=2 127fi 128if [ $opt_name -eq 1 -o $opt_pid -eq 1 ]; then 129 filter=1 130fi 131 132 133################################# 134# --- Main Program, DTrace --- 135# 136/usr/sbin/dtrace -n ' 137 /* 138 * Command line arguments 139 */ 140 inline int OPT_dump = '$opt_dump'; 141 inline int OPT_file = '$opt_file'; 142 inline int OPT_args = '$opt_args'; 143 inline int OPT_cwd = '$opt_cwd'; 144 inline int OPT_err = '$opt_err'; 145 inline int OPT_zone = '$opt_zone'; 146 inline int OPT_time = '$opt_time'; 147 inline int OPT_timestr = '$opt_timestr'; 148 inline int OPT_failonly = '$opt_failonly'; 149 inline int OPT_pid = '$opt_pid'; 150 inline int OPT_name = '$opt_name'; 151 inline int FILTER = '$filter'; 152 inline int PID = '$pid'; 153 inline string PATHNAME = "'$pathname'"; 154 inline string NAME = "'$pname'"; 155 156 #pragma D option quiet 157 #pragma D option switchrate=10hz 158 159 /* 160 * Print header 161 */ 162 dtrace:::BEGIN 163 { 164 /* 165 * ternary operators are used to improve performance. 166 * OPT_args is unusual in that it can have one of three values. 167 */ 168 169 /* print optional headers */ 170 OPT_time ? printf("%-14s ", "TIME") : 1; 171 OPT_timestr ? printf("%-20s ", "STRTIME") : 1; 172 OPT_zone ? printf("%-10s ", "ZONE") : 1; 173 174 /* print dump headers */ 175 OPT_dump ? printf("%s %s %s %s %s %s %s %s %s %s %s", "ZONE", 176 "TIME", "UID", "PID", "PPID", "COMM", "FD", "ERR", "CWD", 177 "PATH", "ARGS") : printf("%5s %6s ","UID","PID"); 178 179 /* print main headers */ 180 OPT_args == 0 ? printf("%-12s ", "COMM") : 1; 181 OPT_dump == 0 ? printf("%3s ", "FD") : 1; 182 OPT_err ? printf("%3s ", "ERR") : 1; 183 OPT_cwd ? printf("%-20s ", "CWD") : 1; 184 OPT_dump == 0 ? printf("%-20s ", "PATH") : 1; 185 OPT_args == 1 ? printf("%s", "ARGS") : 1; 186 printf("\n"); 187 } 188 189 /* 190 * Print open event 191 */ 192 syscall::open:entry 193 { 194 /* save pathname */ 195 self->pathp = arg0; 196 197 /* default is to trace unless filtering */ 198 self->ok = FILTER ? 0 : 1; 199 200 /* check each filter */ 201 (OPT_name == 1 && NAME == execname) ? self->ok = 1 : 1; 202 (OPT_pid == 1 && PID == pid) ? self->ok = 1 : 1; 203 /* OPT_file is checked on return to ensure pathp is mapped */ 204 } 205 206 syscall::open:return 207 /self->ok && (! OPT_failonly || (int)arg0 < 0) && 208 ((OPT_file == 0) || (OPT_file == 1 && PATHNAME == copyinstr(self->pathp)))/ 209 { 210 /* print optional fields */ 211 OPT_time ? printf("%-14d ", timestamp/1000) : 1; 212 OPT_timestr ? printf("%-20Y ", walltimestamp) : 1; 213 OPT_zone ? printf("%-10s ", zonename) : 1; 214 215 /* print dump fields */ 216 OPT_dump ? printf("%s %d %d %d %d %s %d %d %s %s %S", zonename, 217 timestamp/1000, uid, pid, ppid, execname, (int)arg0, errno, 218 cwd, copyinstr(self->pathp), curpsinfo->pr_psargs) : 219 printf("%5d %6d ", uid, pid); 220 221 /* print main fields */ 222 OPT_args == 0 ? printf("%-12s ", execname) : 1; 223 OPT_dump == 0 ? printf("%3d ", (int)arg0) : 1; 224 OPT_err ? printf("%3d ", errno) : 1; 225 OPT_cwd ? printf("%-20s ", cwd) : 1; 226 OPT_dump == 0 ? printf("%-20s ", copyinstr(self->pathp)) : 1; 227 OPT_args == 1 ? printf("%S", curpsinfo->pr_psargs) : 1; 228 printf("\n"); 229 230 /* cleanup */ 231 self->pathp = 0; 232 self->ok = 0; 233 } 234 235 /* 236 * Cleanup 237 */ 238 syscall::open:return 239 /self->ok/ 240 { 241 self->pathp = 0; 242 self->ok = 0; 243 } 244' 245