Created
March 22, 2011 21:10
-
-
Save eqhmcow/882068 to your computer and use it in GitHub Desktop.
logger.pl reimplements (most of) logger(1). Thanks to Perl, this logger hasn't got arbitrary message length limits; so you can syslog(3) messages bigger than the default logger(1) buffer (usually 1k) -- as long as your syslogd supports doing that.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
use strict; | |
use warnings; | |
=pod | |
=head1 NAME | |
B<logger.pl> - a shell command interface to the syslog(3) system log module | |
=head1 SYNOPSIS | |
B<logger.pl> [B<-is>] [B<-f> I<file>] [B<-p> I<pri>] [B<-t> I<tag>] [I<message ...>] | |
=head1 DESCRIPTION | |
Logger makes entries in the system log. It provides a shell command interface | |
to the syslog(3) system log module. | |
Logger.pl reimplements (most of) logger(1). Thanks to Perl, this logger hasn't | |
got arbitrary message length limits; so you can syslog(3) messages bigger than | |
the default logger(1) buffer (usually 1k) -- as long as your syslogd supports | |
doing that. | |
Options: | |
B<-i> Log the process id of the logger process with each line. | |
B<-s> Log the message to standard error, as well as the system log. | |
B<-f> I<file> Log the specified file. | |
B<-p> I<pri> Enter the message with the specified priority. The priority may be specified numerically or as a ``facility.level'' pair. For example, ``-p local3.info'' logs the message(s) as I<info>rmational level in the I<local3> facility. The default is ``user.notice.'' | |
B<-t> I<tag> Mark every line in the log with the specified tag. | |
-- End the argument list. This is to allow the I<message> to start with a hyphen (-). | |
I<message> Write the message to log; if not specified, and the -f flag is not provided, standard input is logged. | |
Valid facility names are: auth, authpriv (for security information of a sensitive nature), cron, daemon, ftp, kern, lpr, mail, news, security (deprecated synonym for auth), syslog, user, uucp, and local0 to local7, inclusive. | |
Valid level names are: alert, crit, debug, emerg, err, error (deprecated synonym for err), info, notice, panic (deprecated synonym for emerg), warning, warn (deprecated synonym for warning). For the priority order and intended purposes of these levels, see syslog(3). | |
Logger.pl attempts to be fully compatible with util-linux's logger (which is | |
descended from BSD's logger.) | |
=cut | |
use Scalar::Util (); | |
use Unix::Syslog qw/:macros :subs/; | |
use Getopt::Long; | |
use Pod::Usage; | |
our $DEFAULT_P = 'user.notice'; | |
my %facility_map = ( | |
'auth' => LOG_AUTH, | |
'security' => LOG_AUTH, | |
'authpriv' => LOG_AUTHPRIV, | |
'cron' => LOG_CRON, | |
'daemon' => LOG_DAEMON, | |
'ftp' => LOG_FTP, | |
'kern' => LOG_KERN, | |
'lpr' => LOG_LPR, | |
'mail' => LOG_MAIL, | |
'news' => LOG_NEWS, | |
'syslog' => LOG_SYSLOG, | |
'user' => LOG_USER, | |
'uucp' => LOG_UUCP, | |
'local0' => LOG_LOCAL0, | |
'local1' => LOG_LOCAL1, | |
'local2' => LOG_LOCAL2, | |
'local3' => LOG_LOCAL3, | |
'local4' => LOG_LOCAL4, | |
'local5' => LOG_LOCAL5, | |
'local6' => LOG_LOCAL6, | |
'local7' => LOG_LOCAL7, | |
); | |
my %priority_map = ( | |
'alert' => LOG_ALERT, | |
'crit' => LOG_CRIT, | |
'debug' => LOG_DEBUG, | |
'emerg' => LOG_EMERG, | |
'panic' => LOG_EMERG, | |
'err' => LOG_ERR, | |
'error' => LOG_ERR, | |
'info' => LOG_INFO, | |
'notice' => LOG_NOTICE, | |
'warning' => LOG_WARNING, | |
'warn' => LOG_WARNING, | |
); | |
my %options; | |
Getopt::Long::Configure('bundling'); | |
GetOptions( | |
'i' => \$options{'i'}, | |
's' => \$options{'s'}, | |
'f=s' => \$options{'f'}, | |
'p=s' => \$options{'p'}, | |
't=s' => \$options{'t'}, | |
) or pod2usage(2); | |
my $message; | |
$message = join ' ', @ARGV if @ARGV; | |
my $file = $options{'f'}; | |
pod2usage("$0: Can't log both message and file") | |
if defined $message and defined $file; | |
# determine priority and facility | |
my $facility = $options{'p'}; | |
$facility = $DEFAULT_P unless defined $facility; | |
$facility =~ m/^([^.]+)\.(.+)$/ | |
or pod2usage("$0: unknown facility name: $facility"); | |
$facility = $1; | |
my $priority = $2; | |
unless (Scalar::Util::looks_like_number($facility)) { | |
$facility = $facility_map{$facility}; | |
defined $facility | |
or pod2usage("$0: unknown facility name: " . $options{'p'}); | |
} | |
unless (Scalar::Util::looks_like_number($priority)) { | |
$priority = $priority_map{$priority}; | |
defined $priority | |
or pod2usage("$0: unknown priority name: " . $options{'p'}); | |
} | |
# redirect stdin if we're logging a file | |
# NOTE: the Perlly way to do this would be: | |
# @ARGV = $file; | |
# however, the C version of logger reopens stdin, which can have subtle | |
# implications - e.g. getlogin() may fail. To maintain compatiblility, we do | |
# what the C version does. | |
if (defined $file) { | |
open(STDIN, '<', $file) | |
or pod2usage("$0: $file: $!"); | |
} | |
# determine tag | |
my $tag = $options{'t'}; | |
# fall back to "logger" if getlogin() fails | |
$tag = getlogin() || 'logger' unless defined $tag; | |
# determine flags | |
$options{'i'} = $options{'i'} ? LOG_PID : 0; | |
$options{'s'} = $options{'s'} ? LOG_PERROR : 0; | |
my $flags = $options{'i'} | $options{'s'}; | |
# openlog | |
# NOTE: openlog(3) doesn't have a lot of error handling... | |
openlog($tag, $flags, $facility); | |
# syslog | |
if (defined $message) { | |
# NOTE: syslog(3) doesn't have a lot of error-handling... | |
syslog($priority, '%s', $message); | |
exit 0; | |
} | |
while (<>) { | |
# NOTE: syslog(3) doesn't have a lot of error-handling... | |
syslog($priority, '%s', $_); | |
} | |
exit 0; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
turns out this is faster than the standard C logger, because Perl's readline routine is better than logger's fgets loop