opensnoop revision 235368
1235368Sgnn#!/usr/bin/sh 2235368Sgnn# 3235368Sgnn# opensnoop - snoop file opens as they occur. 4235368Sgnn# Written using DTrace (Solaris 10 3/05). 5235368Sgnn# 6235368Sgnn# $Id: opensnoop 3 2007-08-01 10:50:08Z brendan $ 7235368Sgnn# 8235368Sgnn# USAGE: opensnoop [-a|-A|-ceghsvxZ] [-f pathname] [-n name] [-p PID] 9235368Sgnn# 10235368Sgnn# opensnoop # default output 11235368Sgnn# 12235368Sgnn# -a # print most data 13235368Sgnn# -A # dump all data, space delimited 14235368Sgnn# -c # print cwd of process 15235368Sgnn# -e # print errno value 16235368Sgnn# -g # print command arguments 17235368Sgnn# -s # print start time, us 18235368Sgnn# -v # print start time, string 19235368Sgnn# -x # only print failed opens 20235368Sgnn# -Z # print zonename 21235368Sgnn# -f pathname # file pathname to snoop 22235368Sgnn# -n name # command name to snoop 23235368Sgnn# -p PID # process ID to snoop 24235368Sgnn# eg, 25235368Sgnn# opensnoop -v # human readable timestamps 26235368Sgnn# opensnoop -e # see error codes 27235368Sgnn# opensnoop -f /etc/passwd # snoop this file only 28235368Sgnn# 29235368Sgnn# FIELDS: 30235368Sgnn# ZONE Zone name 31235368Sgnn# UID User ID 32235368Sgnn# PID Process ID 33235368Sgnn# PPID Parent Process ID 34235368Sgnn# FD file descriptor (-1 for error) 35235368Sgnn# ERR errno value (see /usr/include/sys/errno.h) 36235368Sgnn# CWD print current working directory of process 37235368Sgnn# PATH pathname for file open 38235368Sgnn# COMM command name for the process 39235368Sgnn# ARGS argument listing for the process 40235368Sgnn# TIME timestamp for the open event, us 41235368Sgnn# STRTIME timestamp for the open event, string 42235368Sgnn# 43235368Sgnn# SEE ALSO: truss, BSM auditing. 44235368Sgnn# 45235368Sgnn# COPYRIGHT: Copyright (c) 2006 Brendan Gregg. 46235368Sgnn# 47235368Sgnn# CDDL HEADER START 48235368Sgnn# 49235368Sgnn# The contents of this file are subject to the terms of the 50235368Sgnn# Common Development and Distribution License, Version 1.0 only 51235368Sgnn# (the "License"). You may not use this file except in compliance 52235368Sgnn# with the License. 53235368Sgnn# 54235368Sgnn# You can obtain a copy of the license at Docs/cddl1.txt 55235368Sgnn# or http://www.opensolaris.org/os/licensing. 56235368Sgnn# See the License for the specific language governing permissions 57235368Sgnn# and limitations under the License. 58235368Sgnn# 59235368Sgnn# CDDL HEADER END 60235368Sgnn# 61235368Sgnn# Author: Brendan Gregg [Sydney, Australia] 62235368Sgnn# 63235368Sgnn# 09-May-2004 Brendan Gregg Created this. 64235368Sgnn# 21-Jan-2005 " " Wrapped in sh to provide options. 65235368Sgnn# 08-May-2005 " " Rewritten for performance. 66235368Sgnn# 14-May-2005 " " Added errno. 67235368Sgnn# 28-Jun-2005 " " Added cwd, zonename. 68235368Sgnn# 17-Sep-2005 " " Increased switchrate, fixed page fault bug. 69235368Sgnn# 16-Jan-2006 " " Added -n, -p. 70235368Sgnn# 16-Jan-2006 " " Last update. 71235368Sgnn# 72235368Sgnn 73235368Sgnn 74235368Sgnn############################## 75235368Sgnn# --- Process Arguments --- 76235368Sgnn# 77235368Sgnn 78235368Sgnn### Default variables 79235368Sgnnopt_dump=0; opt_file=0; opt_time=0; opt_timestr=0; opt_args=0 80235368Sgnnopt_zone=0; opt_cwd=0; opt_failonly=0; opt_err=0; filter=0; pathname=. 81235368Sgnnopt_name=0; opt_pid=0; pname=.; pid=0 82235368Sgnn 83235368Sgnn### Process options 84235368Sgnnwhile getopts aAcef:ghn:p:svxZ name 85235368Sgnndo 86235368Sgnn case $name in 87235368Sgnn a) opt_time=1; opt_timestr=1; opt_args=1; opt_err=1 ;; 88235368Sgnn A) opt_dump=1 ;; 89235368Sgnn c) opt_cwd=1 ;; 90235368Sgnn e) opt_err=1 ;; 91235368Sgnn g) opt_args=1 ;; 92235368Sgnn f) opt_file=1; pathname=$OPTARG ;; 93235368Sgnn n) opt_name=1; pname=$OPTARG ;; 94235368Sgnn p) opt_pid=1; pid=$OPTARG ;; 95235368Sgnn s) opt_time=1 ;; 96235368Sgnn v) opt_timestr=1 ;; 97235368Sgnn x) opt_failonly=1 ;; 98235368Sgnn Z) opt_zone=1 ;; 99235368Sgnn h|?) cat <<-END >&2 100235368Sgnn USAGE: opensnoop [-a|-A|-ceghsvxZ] [-f pathname] 101235368Sgnn [-n name] [-p PID] 102235368Sgnn opensnoop # default output 103235368Sgnn -a # print most data 104235368Sgnn -A # dump all data, space delimited 105235368Sgnn -c # print cwd of process 106235368Sgnn -e # print errno value 107235368Sgnn -g # print command arguments 108235368Sgnn -s # print start time, us 109235368Sgnn -v # print start time, string 110235368Sgnn -x # only print failed opens 111235368Sgnn -Z # print zonename 112235368Sgnn -f pathname # pathname name to snoop 113235368Sgnn -n name # process name to snoop 114235368Sgnn -p PID # process ID to snoop 115235368Sgnn eg, 116235368Sgnn opensnoop -v # human readable timestamps 117235368Sgnn opensnoop -e # see error codes 118235368Sgnn opensnoop -f /etc/motd # snoop this file only 119235368Sgnn END 120235368Sgnn exit 1 121235368Sgnn esac 122235368Sgnndone 123235368Sgnn 124235368Sgnn### Option logic 125235368Sgnnif [ $opt_dump -eq 1 ]; then 126235368Sgnn opt_zone=0; opt_cwd=0; opt_time=0; opt_timestr=0; opt_args=2 127235368Sgnnfi 128235368Sgnnif [ $opt_name -eq 1 -o $opt_pid -eq 1 ]; then 129235368Sgnn filter=1 130235368Sgnnfi 131235368Sgnn 132235368Sgnn 133235368Sgnn################################# 134235368Sgnn# --- Main Program, DTrace --- 135235368Sgnn# 136235368Sgnn/usr/sbin/dtrace -n ' 137235368Sgnn /* 138235368Sgnn * Command line arguments 139235368Sgnn */ 140235368Sgnn inline int OPT_dump = '$opt_dump'; 141235368Sgnn inline int OPT_file = '$opt_file'; 142235368Sgnn inline int OPT_args = '$opt_args'; 143235368Sgnn inline int OPT_cwd = '$opt_cwd'; 144235368Sgnn inline int OPT_err = '$opt_err'; 145235368Sgnn inline int OPT_zone = '$opt_zone'; 146235368Sgnn inline int OPT_time = '$opt_time'; 147235368Sgnn inline int OPT_timestr = '$opt_timestr'; 148235368Sgnn inline int OPT_failonly = '$opt_failonly'; 149235368Sgnn inline int OPT_pid = '$opt_pid'; 150235368Sgnn inline int OPT_name = '$opt_name'; 151235368Sgnn inline int FILTER = '$filter'; 152235368Sgnn inline int PID = '$pid'; 153235368Sgnn inline string PATHNAME = "'$pathname'"; 154235368Sgnn inline string NAME = "'$pname'"; 155235368Sgnn 156235368Sgnn #pragma D option quiet 157235368Sgnn #pragma D option switchrate=10hz 158235368Sgnn 159235368Sgnn /* 160235368Sgnn * Print header 161235368Sgnn */ 162235368Sgnn dtrace:::BEGIN 163235368Sgnn { 164235368Sgnn /* 165235368Sgnn * ternary operators are used to improve performance. 166235368Sgnn * OPT_args is unusual in that it can have one of three values. 167235368Sgnn */ 168235368Sgnn 169235368Sgnn /* print optional headers */ 170235368Sgnn OPT_time ? printf("%-14s ", "TIME") : 1; 171235368Sgnn OPT_timestr ? printf("%-20s ", "STRTIME") : 1; 172235368Sgnn OPT_zone ? printf("%-10s ", "ZONE") : 1; 173235368Sgnn 174235368Sgnn /* print dump headers */ 175235368Sgnn OPT_dump ? printf("%s %s %s %s %s %s %s %s %s %s %s", "ZONE", 176235368Sgnn "TIME", "UID", "PID", "PPID", "COMM", "FD", "ERR", "CWD", 177235368Sgnn "PATH", "ARGS") : printf("%5s %6s ","UID","PID"); 178235368Sgnn 179235368Sgnn /* print main headers */ 180235368Sgnn OPT_args == 0 ? printf("%-12s ", "COMM") : 1; 181235368Sgnn OPT_dump == 0 ? printf("%3s ", "FD") : 1; 182235368Sgnn OPT_err ? printf("%3s ", "ERR") : 1; 183235368Sgnn OPT_cwd ? printf("%-20s ", "CWD") : 1; 184235368Sgnn OPT_dump == 0 ? printf("%-20s ", "PATH") : 1; 185235368Sgnn OPT_args == 1 ? printf("%s", "ARGS") : 1; 186235368Sgnn printf("\n"); 187235368Sgnn } 188235368Sgnn 189235368Sgnn /* 190235368Sgnn * Print open event 191235368Sgnn */ 192235368Sgnn syscall::open:entry, syscall::open64:entry 193235368Sgnn { 194235368Sgnn /* save pathname */ 195235368Sgnn self->pathp = arg0; 196235368Sgnn 197235368Sgnn /* default is to trace unless filtering */ 198235368Sgnn self->ok = FILTER ? 0 : 1; 199235368Sgnn 200235368Sgnn /* check each filter */ 201235368Sgnn (OPT_name == 1 && NAME == execname) ? self->ok = 1 : 1; 202235368Sgnn (OPT_pid == 1 && PID == pid) ? self->ok = 1 : 1; 203235368Sgnn /* OPT_file is checked on return to ensure pathp is mapped */ 204235368Sgnn } 205235368Sgnn 206235368Sgnn syscall::open:return, syscall::open64:return 207235368Sgnn /self->ok && (! OPT_failonly || (int)arg0 < 0) && 208235368Sgnn ((OPT_file == 0) || (OPT_file == 1 && PATHNAME == copyinstr(self->pathp)))/ 209235368Sgnn { 210235368Sgnn /* print optional fields */ 211235368Sgnn OPT_time ? printf("%-14d ", timestamp/1000) : 1; 212235368Sgnn OPT_timestr ? printf("%-20Y ", walltimestamp) : 1; 213235368Sgnn OPT_zone ? printf("%-10s ", zonename) : 1; 214235368Sgnn 215235368Sgnn /* print dump fields */ 216235368Sgnn OPT_dump ? printf("%s %d %d %d %d %s %d %d %s %s %S", zonename, 217235368Sgnn timestamp/1000, uid, pid, ppid, execname, (int)arg0, errno, 218235368Sgnn cwd, copyinstr(self->pathp), curpsinfo->pr_psargs) : 219235368Sgnn printf("%5d %6d ", uid, pid); 220235368Sgnn 221235368Sgnn /* print main fields */ 222235368Sgnn OPT_args == 0 ? printf("%-12s ", execname) : 1; 223235368Sgnn OPT_dump == 0 ? printf("%3d ", (int)arg0) : 1; 224235368Sgnn OPT_err ? printf("%3d ", errno) : 1; 225235368Sgnn OPT_cwd ? printf("%-20s ", cwd) : 1; 226235368Sgnn OPT_dump == 0 ? printf("%-20s ", copyinstr(self->pathp)) : 1; 227235368Sgnn OPT_args == 1 ? printf("%S", curpsinfo->pr_psargs) : 1; 228235368Sgnn printf("\n"); 229235368Sgnn 230235368Sgnn /* cleanup */ 231235368Sgnn self->pathp = 0; 232235368Sgnn self->ok = 0; 233235368Sgnn } 234235368Sgnn 235235368Sgnn /* 236235368Sgnn * Cleanup 237235368Sgnn */ 238235368Sgnn syscall::open:return, syscall::open64:return 239235368Sgnn /self->ok/ 240235368Sgnn { 241235368Sgnn self->pathp = 0; 242235368Sgnn self->ok = 0; 243235368Sgnn } 244235368Sgnn' 245