Skip to content

Instantly share code, notes, and snippets.

@eqhmcow
Created March 22, 2011 21:10
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eqhmcow/882068 to your computer and use it in GitHub Desktop.
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.
#!/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;
@eqhmcow
Copy link
Author

eqhmcow commented Nov 8, 2019

turns out this is faster than the standard C logger, because Perl's readline routine is better than logger's fgets loop

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment