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