1*c29d5175Schristos#!/usr/bin/perl 2*c29d5175Schristos# 3*c29d5175Schristos# errinfo - report on syscall failures and print errno error messages. 4*c29d5175Schristos# Written using Perl and DTrace (Solaris 10 03/05) 5*c29d5175Schristos# 6*c29d5175Schristos# When system calls fail, an errno variable is set to convay a meaningful 7*c29d5175Schristos# message to the end user - so long as the program does something with it 8*c29d5175Schristos# (eg, "ls" printing "No such file or directory"). This program fetches 9*c29d5175Schristos# and prints details for all syscall failures along with their message, 10*c29d5175Schristos# whether the failing program is already printing this info or not. 11*c29d5175Schristos# 12*c29d5175Schristos# $Id: errinfo,v 1.1.1.1 2015/09/30 22:01:07 christos Exp $ 13*c29d5175Schristos# 14*c29d5175Schristos# USAGE: errinfo [-ch] [-p PID] [-n name] 15*c29d5175Schristos# 16*c29d5175Schristos# -c # counts - aggregate style 17*c29d5175Schristos# -p PID # examine this PID only 18*c29d5175Schristos# -n name # examine processes with this name only 19*c29d5175Schristos# eg, 20*c29d5175Schristos# errinfo # default output - snoop event style 21*c29d5175Schristos# errinfo -n ssh # examine "ssh" processes only 22*c29d5175Schristos# errinfo -cn ssh # examine "ssh" using counts 23*c29d5175Schristos# 24*c29d5175Schristos# FIELDS: 25*c29d5175Schristos# EXEC Program name (truncated) 26*c29d5175Schristos# SYSCALL System call name 27*c29d5175Schristos# ERR Value of errno 28*c29d5175Schristos# DESC Description of errno message 29*c29d5175Schristos# 30*c29d5175Schristos# SEE ALSO: /usr/include/sys/errno.h 31*c29d5175Schristos# 32*c29d5175Schristos# COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg. 33*c29d5175Schristos# 34*c29d5175Schristos# CDDL HEADER START 35*c29d5175Schristos# 36*c29d5175Schristos# The contents of this file are subject to the terms of the 37*c29d5175Schristos# Common Development and Distribution License, Version 1.0 only 38*c29d5175Schristos# (the "License"). You may not use this file except in compliance 39*c29d5175Schristos# with the License. 40*c29d5175Schristos# 41*c29d5175Schristos# You can obtain a copy of the license at Docs/cddl1.txt 42*c29d5175Schristos# or http://www.opensolaris.org/os/licensing. 43*c29d5175Schristos# See the License for the specific language governing permissions 44*c29d5175Schristos# and limitations under the License. 45*c29d5175Schristos# 46*c29d5175Schristos# CDDL HEADER END 47*c29d5175Schristos# 48*c29d5175Schristos# Author: Brendan Gregg [Sydney, Australia] 49*c29d5175Schristos# 50*c29d5175Schristos# 18-Apr-2005 Brendan Gregg Created this. 51*c29d5175Schristos# 20-Apr-2006 " " Last update. 52*c29d5175Schristos# 53*c29d5175Schristos 54*c29d5175Schristosuse Getopt::Std; 55*c29d5175Schristos 56*c29d5175Schristos# 57*c29d5175Schristos# Defaults 58*c29d5175Schristos# 59*c29d5175Schristos$FILTER = ""; 60*c29d5175Schristos$COUNT = 0; 61*c29d5175Schristos 62*c29d5175Schristos# 63*c29d5175Schristos# Command line arguments 64*c29d5175Schristos# 65*c29d5175Schristos&Usage() if $ARGV[0] eq "--help"; 66*c29d5175Schristosgetopts('ch:n:p:') || &Usage(); 67*c29d5175Schristos&Usage() if $opt_h; 68*c29d5175Schristos$COUNT = 1 if $opt_c; 69*c29d5175Schristos$FILTER = "&& execname == \"$opt_n\"" if defined $opt_n; 70*c29d5175Schristos$FILTER = "&& pid == $opt_p" if defined $opt_p; 71*c29d5175Schristos 72*c29d5175Schristos# 73*c29d5175Schristos# Load errno descriptions 74*c29d5175Schristos# 75*c29d5175Schristosopen(ERRNO,"/usr/include/sys/errno.h") || die "ERROR1: reading errno.h: $!\n"; 76*c29d5175Schristoswhile (chomp($line = <ERRNO>)) { 77*c29d5175Schristos next unless $line =~ /^#define/; 78*c29d5175Schristos ($errno,$desc) = $line =~ /^#define\s+\S+\s+(\d+)\s+\/\*(.*)\*\//; 79*c29d5175Schristos $Errno{$errno} = $desc; 80*c29d5175Schristos} 81*c29d5175Schristosclose ERRNO; 82*c29d5175Schristos 83*c29d5175Schristos# 84*c29d5175Schristos# Declare DTrace script 85*c29d5175Schristos# 86*c29d5175Schristos if ($COUNT) { # aggregate style 87*c29d5175Schristos$dtrace = <<END; 88*c29d5175Schristos/usr/sbin/dtrace -n ' 89*c29d5175Schristos #pragma D option quiet 90*c29d5175Schristos syscall:::return 91*c29d5175Schristos /errno != 0 && pid != \$pid $FILTER/ 92*c29d5175Schristos { 93*c29d5175Schristos \@Errs[execname, probefunc, errno] = count(); 94*c29d5175Schristos } 95*c29d5175Schristos dtrace:::END { 96*c29d5175Schristos printa("%s %s %d %\@d\\n", \@Errs); 97*c29d5175Schristos }' 98*c29d5175SchristosEND 99*c29d5175Schristos } else { # snoop style 100*c29d5175Schristos$dtrace = <<END; 101*c29d5175Schristos/usr/sbin/dtrace -n ' 102*c29d5175Schristos #pragma D option quiet 103*c29d5175Schristos #pragma D option switchrate=5hz 104*c29d5175Schristos syscall:::return 105*c29d5175Schristos /errno != 0 && pid != \$pid $FILTER/ 106*c29d5175Schristos { 107*c29d5175Schristos printf("%s %s %d\\n", execname, probefunc, errno); 108*c29d5175Schristos }' 109*c29d5175SchristosEND 110*c29d5175Schristos } 111*c29d5175Schristos 112*c29d5175Schristos# 113*c29d5175Schristos# Cleanup on signals 114*c29d5175Schristos# 115*c29d5175Schristos$SIG{INT} = \&Cleanup_Signal; # Ctrl-C 116*c29d5175Schristos$SIG{QUIT} = \&Cleanup_Signal; # Ctrl-\ 117*c29d5175Schristos$SIG{TERM} = \&Cleanup_Signal; # TERM 118*c29d5175Schristos 119*c29d5175Schristos# 120*c29d5175Schristos# Run DTrace, process output 121*c29d5175Schristos# 122*c29d5175Schristos 123*c29d5175Schristosif ($COUNT) { 124*c29d5175Schristos print STDERR "Tracing... Hit Ctrl-C to end.\n"; 125*c29d5175Schristos $header = 1; 126*c29d5175Schristos} else { 127*c29d5175Schristos printf("%16s %16s %4s %s\n","EXEC","SYSCALL","ERR","DESC"); 128*c29d5175Schristos} 129*c29d5175Schristos 130*c29d5175Schristos### Open DTrace 131*c29d5175Schristosopen(DTRACE,"$dtrace |") || die "ERROR2: Can't start dtrace (perms?): $!\n"; 132*c29d5175Schristos 133*c29d5175Schristos### Process DTrace output 134*c29d5175Schristoswhile (chomp($line = <DTRACE>)) { 135*c29d5175Schristos 136*c29d5175Schristos ### Print count header 137*c29d5175Schristos if ($COUNT && $header) { 138*c29d5175Schristos printf("\n%16s %16s %4s %6s %s\n", 139*c29d5175Schristos "EXEC","SYSCALL","ERR","COUNT","DESC"); 140*c29d5175Schristos $header = 0; 141*c29d5175Schristos } 142*c29d5175Schristos 143*c29d5175Schristos ### Split data 144*c29d5175Schristos ($execname,$syscall,$errno,$counts) = split(' ',$line); 145*c29d5175Schristos next if $errno eq ""; 146*c29d5175Schristos 147*c29d5175Schristos ### Fetch errno description 148*c29d5175Schristos $desc = $Errno{$errno}; 149*c29d5175Schristos 150*c29d5175Schristos ### Print output line 151*c29d5175Schristos if ($COUNT) { 152*c29d5175Schristos printf("%16s %16s %4d %6d %s\n", 153*c29d5175Schristos $execname,$syscall,$errno,$counts,$desc); 154*c29d5175Schristos } else { 155*c29d5175Schristos printf("%16s %16s %4d %s\n",$execname,$syscall,$errno,$desc); 156*c29d5175Schristos } 157*c29d5175Schristos} 158*c29d5175Schristosclose(DTRACE); 159*c29d5175Schristos 160*c29d5175Schristos# 161*c29d5175Schristos# Triggered by signals 162*c29d5175Schristos# 163*c29d5175Schristossub Cleanup_Signal { 164*c29d5175Schristos} 165*c29d5175Schristos 166*c29d5175Schristos# 167*c29d5175Schristos# Usage message 168*c29d5175Schristos# 169*c29d5175Schristossub Usage { 170*c29d5175Schristos print STDERR "USAGE: errinfo [-ch] [-p PID] [-n name]\n"; 171*c29d5175Schristos print STDERR <<ENDUSAGE; 172*c29d5175Schristos eg, 173*c29d5175Schristos errinfo # default output - snoop event style 174*c29d5175Schristos -c # counts - aggregate style 175*c29d5175Schristos -p 871 # examine PID 871 only 176*c29d5175Schristos -n ssh # examine processes with the name "ssh" only 177*c29d5175Schristos -cn ssh # examine "ssh" using counts 178*c29d5175SchristosENDUSAGE 179*c29d5175Schristos exit(1); 180*c29d5175Schristos} 181