errinfo revision 1.1 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 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