Home | History | Annotate | Line # | Download | only in Bin
      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