arlogd - a remote logger
arlogd-server [-h] [-s] [-t] [--version] [-c config] [start|stop|state] arlogd-client [-h] [-s] [-t] [--version] [-c config] [start|stop|state]
Arlogd provides remote logging ; a daemon on the client host transfers data to a daemon on the server host (loghost).
Programs on a client host use remote logging by writing to a named pipe (fifo).
On a client, a daemon periodicly searches directory $fifos
(default /var/log/fifos
) for readable fifo's.
Note : a fifo is created with mkfifo /var/log/fifos/my-fifo
Anything written into such a fifo, appears immediately in a corresponding file on the loghost :
client: /var/log/fifos/foo/bar loghost: /var/log/arlog/foo/bar
Start the (loghost or client) daemon with :
arlogd-server start arlogd-client start
The exit status is 0 if a daemon is started (or was already running) ; 1 otherwise.
Stop a daemon with :
arlogd-server stop arlogd-client stop
The exit status is 0 if a daemon was stopped (or wasn't running) ; 1 otherwise.
To query the running daemon's state, use argument state
:
arlogd-server state arlogd-client state
The daemon reports :
the current list of open logfiles (server) or watched fifos (client),
the current incoming and outgoing connections,
the service ports it is listening on.
The exit status is 0.
Without an argument, arlogd-server
and arlogd-client
just shows the daemon's status.
arlogd-server arlogd-client
The exit status is 0 if the daemon is running ; 1 otherwise.
The default location for a config-file is
arlogd.conf
or /etc/arlogd/conf
.
If/when $loghost is unavailable, the client will :
save log-entries in a file in $save_dir (default /var/log/arlogd-save
) ;
periodicly try to reconnect to $loghost ;
on reconnect, send $save_dir/
$loghost.log
to $loghost.
You can send commands to a running daemon ; see ARLOGD-SERVER and ARLOGD-CLIENT below.
See below :
IMPORTANT : notes on using arlogd in production
more on logging
To use remote logging for some logfile, just replace the logfile by a symlink to a fifo :
# remote logging for /var/log/httpd/vhost/access.log
% mkdir -p /var/log/fifos/httpd/vhost/ % mkfifo /var/log/fifos/httpd/vhost/access.log % cd /var/log/apache % mv access.log TEMP % ln -s /var/log/fifos/httpd/vhost/access.log . % cat TEMP > access.log
Things to check or do :
Restart utilities that keep their logfile open. Some (like apache) do, others (like rsync) don't.
fuser TEMP
may tell you which processes are still using TEMP
.
Remove TEMP
.
Don't forget to turn off log processing (like log-rotation
by logrotate(8)
or other processes) for the logfile you just
made remote.
Show help and default config ; then exit.
Be silent ; use logs instead of stdout ; used in init.d/
scripts.
Just check the config.
Just print the version and exit.
Use config file.
A configuration file must be specified with -c config-file or be present as
./arlogd.conf /etc/arlogd/conf
In the config-file, lines starting with #
are skipped ; as are empty
lines ; lines with leading and/or trailing white space are stripped.
Each line contains a name/value pair, separated by white space.
The list below shows the default value for each name. $name indicates the configured value of entry name.
loghost localhost
Clients send their data to host $loghost.
Specify a host.domain name, or an IP address ; eg
loghost loghost.my.org
allow_host
host
allow_host
host prefix
The hosts that are allowed to connect to the $loghost.
By default, localhost
is allowed to connect.
The default prefix is empty (''
).
Configure a allow_host
-line for each allowed host.
allow_host localhost allow_host webfarm.my.org allow_host monitor.my.org
If a prefix is specified, the $loghost prepends a prefix received from host with prefix. For instance, if a client supplies a log-line like
access_log 81.189.215.252 - - [09/Dec/2014:12:49:41 ...
then, by default, the line is appended to $log_dir/access_log
.
However, if you configure :
allow_host webfarm.my.org webfarm/ allow_host monitor.my.org monitor_
log_lines are written to $log_dir/webfarm/access_log
and
$log_dir/monitor_access_log
.
autoflush 1
By default, the daemon on the loghost writes the logfiles with autoflush on : the daemon flushes files after every write.
Autoflush is expensive, but it will keep the contents of the remote logfiles as up-to-date as possible.
It is probably wise to turn off autoflush later, when things are running smoothly.
To turn autoflush off, configure :
autoflush 0
rename_list /etc/arlogd/renames
The specified file should contain a list of (src,dst)-pairs like :
mv file /path/to/dest
Path $file is used relatative to $log_dir ;
that is, $log_dir/
$file should exist.
The $rename_list is used by command RENAME (see below). It attempts to
rename $log_dir/$src $dst
for each (src,dst)-pair.
Renaming can be useful if you want to integrate remote logfile processing (rotation, analysis etc) into your normal process. Use renaming to move your remote logfiles into your normal log-tree, just before normal processing begins.
If the list is long, you should probably generated it ; the list is re-read every time RENAME runs.
log_names *.log
On the loghost, the daemon can manipulate logfiles on demand. Pattern $log_names is the default file name pattern for the daemon.
In pattern, *
means string not containing /
;
it is always used to match as a suffix.
port 2207
The loghost data port ; $port+1 is used on $loghost for commands .
logfile /var/log/arlogd.log
The server- and client-daemons log into file $logfile.
run_dir /var/run/arlogd
The server- and client-daemons keep pid-files etc in directory $run_dir.
log_dir /var/log/arlog
The server on $loghost writes the logs in directory $log_dir.
fifos /var/log/fifos
A client-daemon watches named pipes in directory $fifos.
save_dir /var/log/arlogd-save
If/when the loghost is unavailable,
a client saves log-entries in $save_dir/
$loghost.log
.
reconnect 300
If/when the loghost is unavailable, a client will try to reconnect to the loghost every $reconnect seconds.
On reconnect, the client sends the contents of
$save_dir/
$loghost.log
to $loghost.
upd_fifos 60
A client searches the fifos directory, looking for new (or disappeared) fifo's, every $upd_fifos seconds.
send_timeout 10
A client writing data to a server, will timeout after $send_timeout seconds ; when a timeout occurs the client starts writing to a local file, and will try to reconnect later.
send_connect 5
When a client connects to a server, it will timeout after $send_connect seconds ; when a timeout occurs the client starts writing to a local file, and will try to reconnect later.
recv_timeout 900
The server closes a data-connection when nothing was received in the last $recv_timeout seconds.
Program arlogd-server opens two service ports (default 2207 and 2208).
On port 2207 the daemon accepts data connections from hosts in allow_host. The daemon expects lines like
file-path log-line
The log-line is appended to file $log_dir/
file-path,
or $log_dir/
prefix/
file-path, if the a prefix
is set for the allowed host.
If the log-line starts with /
or contains ..
as a path-component,
the log-line is appended to file $log_dir/BAD.log
.
On port 2208 the daemon accepts command connections from localhost.
To issue a command, on $loghost (for now) use netcat :
echo command | nc -v localhost 2208
These commands let you get/set the value of autoflush in the running daemon.
Command AUTOFLUSH?
gets the value ; it prints :
COMMAND AUTOFLUSH? AUTOFLUSH current_value_autoflush
Commands AUTOFLUSH
and NO_AUTOFLUSH
set the value of
autoflush, and print :
COMMAND [NO_]AUTOFLUSH AUTOFLUSH old_value -> new_value
The daemon closes all files in $log_dir.
Command CLOSE
prints something like :
COMMAND CLOSE FILES 3 FILE: /path/to/file1 FILE: /path/to/file2 FILE: /path/to/file3
If/when the daemon is using (normal) buffered IO ($autoflush is off), and you want to see the actual contents of a remote logfile, then you can use CLOSE to make the daemon close (and thus flush) its open files.
The daemon finds files in $log_dir matching pattern as a suffix ; symlinks are ignored.
The default pattern is $log_names (default *.log
).
Command FIND
prints something like :
COMMAND FIND FILES 3 FILE: /path/to/file1 FILE: /path/to/file2 FILE: /path/to/file3
and possibly some lines like :
ERROR some error
Use FIND to test pattern before you use it in ROTATE
.
On PING, the daemon prints :
PONG
The daemon renames files as indicated in file $rename_list
(default /etc/arlogd/renames
) ; see config entry
rename_list.
File $rename_list must contain lines like
mv file /path/to/dst
where file is a relative path in $log_dir :
RENAME
operates on $log_dir/
file.
Lines starting with #
are skipped, as are empty lines ;
lines with leading and/or trailing white space are stripped.
Because (a priori) RENAME
will move anything anywhere,
we need some constraints :
The owner of the file $rename_list must be the same as the owner
of the (running) daemon executing the RENAME
command.
The daemon trusts that its owner knows what he/she is doing.
The $rename_list must not be group- or world-writable. The daemon trusts only its owner.
RENAME
will not rename file if file is a directory or a symlink.
RENAME
will not rename file to /path/to/dst
if /path/to/dst is a directory or a symlink.
RENAME
will not create in-between directories for
/path/to/dst : /path/to/ must exist.
Please note :
Before each rename
, /path/to/dst is removed ;
so, file /path/to/dst is always lost.
If file is missing, RENAME
attempts to create an empty
file /path/to/dst.
A missing file is assumed to be empty.
If/when you run RENAME
daily, and nothing is logged in file
during the previous day, then file will not exist.
If you want to change the location of the $rename_list, you have to reconfigure and restart the daemon ; this is intentional.
Command RENAME
prints something like :
COMMAND RENAME FILE: $rename_list FILES 3 DONE: /path/to/src1 /path/to/dst1 DONE: /path/to/src2 /path/to/dst2 DONE: /path/to/src3 /path/to/dst3
and possibly some lines like :
ERROR can't open list (why) ERROR can't rename $file (why) ERROR bad line [$line]
or, if file is missing :
WARN: can't find $file DONE: EMPTY /path/to/dst ERROR can't create empty /path/to/dst (why)
The daemon rotates files in $log_dir matching pattern as a suffix.
While searching for targets, symlinks are ignored.
The default pattern is $log_names (default *.log
).
To rotate X means : close X
and rename X
as X.rot
.
arlog/www.my.org/access.log -> arlog/www.my.org/access.log.rot
A separate utility must further rotate, compress, analyse stuff.
Command ROTATE
prints something like :
COMMAND ROTATE FILES 3 FILE: /path/to/file1 FILE: /path/to/file2 FILE: /path/to/file3
and possibly some lines like :
ERROR can't rename /path/to/file
The daemon shows it's state : the current list of open logfiles, the incoming and outgoing connections, and the service ports it is listening on.
The daemon checks the secret, closes all files in $log_dir and stops. The secret is generated by the daemon on start-up.
The daemon writes the secret to $run_dir/server.stp
with mode 0600
,
so command STOP
can only be used by the user who owns the daemon.
Command STOP
prints :
STOPPED
or
BAD SECRET
STOP
is used by arlogd-server
to cleanly stop the running daemon.
A client-daemon watches named pipes in directory $fifos.
A fifo must not have white space in its name, or path-components. Such fifo's are flagged as BAD. They are watched, but anything read from them will be discarded.
Program arlogd-client opens a service port (default 2209), where it accepts command connections from localhost.
To issue a command, on $loghost (for now) use netcat :
echo command | nc -v localhost 2209
On PING, the daemon prints :
PONG
The daemon shows it's state : the fifos it is watching, the incoming and outgoing connections, and the service ports it is listening on.
The daemon checks the secret, closes all fifos in $fifos and stops. The secret is generated by the daemon on start-up.
The daemon writes the secret to $run_dir/client.stp
with mode 0600
,
so command STOP
can only be used by the user who owns the daemon.
Command STOP
prints :
STOPPED
or
BAD SECRET
STOP
is used by arlogd-client
to cleanly stop the running daemon.
Installation of arlogd requires very little :
Perl, perl core-modules IO
, File::Path
, Net::hostent
.
logger(1)
in /bin
, /sbin
, /usr/bin
or /usr/sbin
.
On a loghost, you need netcat nc(1)
if you want to use the daemons
command facility.
Installation is simple :
subversion check-out :
svn co https://svn.science.uu.nl/repos/project.arlogd/pub/trunk arlogd
rsync :
rsync rsync.cs.uu.nl::arlogd
package :
http://www.staff.science.uu.nl/~penni101/arlogd/arlogd.tar.gz
On a server (loghost) :
make -f install-server.mk
On a client :
make -f install-client.mk
Arlogd is added as a service, but the service is not turned on or started. To turn on the service use
chkconfig arlogd-server on chkconfig arlogd-client on
To configure, edit /etc/arlogd/conf
.
On the server (loghost), configure entry
allow_host (default localhost
).
allow_host localhost allow_host webfarm.my.org allow_host monitor.my.org
On a client, configure entry loghost
(default localhost
).
loghost loghost.my.org
On a server (loghost) :
/etc/init.d/arlogd-server start
On a client :
/etc/init.d/arlogd-client start
On the loghost and the client watch the log :
tail -F /var/log/arlogd.log
On the client, make a fifo :
mkfifo /var/log/fifos/test
Within a minute, arlogd-client
will start watching this fifo ;
see the log.
Write something to the fifo :
echo something > /var/log/fifos/test
On the loghost, something should immediately appear in file
/var/log/arlog/test
You can also try to create a fifo in a subdirectory ; and write to it immediately :
mkdir -p /var/log/fifos/foo/bar mkfifo /var/log/fifos/foo/bar/test echo something else > /var/log/fifos/foo/bar/test
Expect echo
to block ; be patient ; echo
is waiting for a reader.
As soon as arlogd-client
finds fifo foo/bar
:
... echo
unblocks ;
and on the loghost, something else appears in
/var/log/arlog/foo/bar/test
On the loghost, you can talk to the daemon if you have netcat nc(1)
.
echo PING | nc localhost 2208
This should reply PONG
.
allow_host
and loghost
Make sure you have configured allow_host (on the loghost) and loghost (on the clients).
The defaults (localhost
for both) are probably not sane.
$GREP_OPTIONS --devices=skip
By default, grep(1)
reads devices, and will hang
when it encounters a fifo ; for instance, when you do
grep -r some-pattern /var/log/
Grep(1)
will silently ignore devices if you set environment variable
GREP_OPTIONS :
$GREP_OPTIONS = --devices=skip
When you do want to grep devices, use
grep --devices=read ...
The daemons should run from (multi-user) boot until shutdown.
Make sure that the arlogd service (server or client) is turned on.
chkconfig --list arlogd-server chkconfig --list arlogd-client
If not, turn on the service with (either) :
chkconfig arlogd-server on chkconfig arlogd-client on
On a client, make sure that arlogd-client
is started early,
because a utility that logs to a fifo will block until
arlogd-client
is started.
Inspect /etc/rc.d/rc2.d/
and assert that S??arlogd-client
is listed
before S??
service for all services that use remote logging.
Less important, check that (on shutdown) arlogd-client
is stopped
late, because you may lose some log-lines when the daemon
(with autoflush off) is stopped too early.
Inspect /etc/rc.d/rc6.d/
and assert that K??arlogd-client
is listed
after K??
service for all services that use remote logging.
Note: to see the init.d
start/stop priorities of arlogd
,
look at /etc/init.d/arlogd-server
and /etc/init.d/arlogd-client
.
The relevant line looks like :
# chkconfig: 2345 $start_prio $stop_prio
Note: configuration management of the daemon-startup-sequence varies wildly between Linux/Unix platforms and installations ; YMMV ...
Every minute, the client deamon has to walk the $fifos-tree,
looking for fifo's. That's cheap if the tree is flat (has only a
few flat sub-directories) ; the flatter, the better.
But if your client isn't very busy, or /var/log/
isn't very big,
you may want to configure
fifos /var/log
and just replace logfiles with fifo's.
Use find(1)
to see how long it takes to walk /var/log
,
looking for fifo's :
time find /var/log -type p -print
Maybe having fifo's in /var/log/
(or in /var/log/fifos/
)
isn't such a good idea.
Think about grep -r ... /var/log/
; it will hang ;
although grep -D skip
will not (it skips devices).
So, if it is
a problem, the default for $fifos should
be something ugly like /dev/arlogd
.
Or, if it isn't
a problem, the default for $fifos
could be /var/log
; that is preferable because it simplifies
usage for Joe average (``just replace a logfile by a fifo'').
Scanning /var/log/
is cheap, unless it is VERY big.
Try : time find /var/log -type p -print
A production note, could tell users with a BIG /var/log/
that it is more efficient to collect their fifo's in some separate directory,
and use symlinks and/or reconfigure their apps to log elsewhere.
Suppose the daemons are running. And suppose you create a named pipe :
mkfifo -m 0755 /var/log/fifos/foo/bar.log
... and some utility writes a log-line to
/var/log/fifos/foo/bar.log
.
Then, on the client, the daemon will :
foo/bar.log
(within a minute),
foo/bar.log
On the loghost, the daemon will :
The loghost only checks that the prefix doesn't
start with /
(slash) and doesn't contain
..
as a path-component.
On the client, the daemon keeps a list of fifo's in $fifos
(default /var/log/fifos
), which it refreshes every minute.
The client daemon watches the fifo's all at once. If/when any fifo has new data, the daemon quickly picks it up and sends it to the loghost.
The server handles incoming connections, processes commands, and stores log-lines in the appropriate log-files.
It maintains a hash of open log-files, indexed by the prefixes it has received.
The server keeps files open, until instructed to close them.
When a command must start
a daemon, it tries to make sure
the daemon will not run into problems immediately.
Note that the launched daemon is entirely detached from the launcher ; the launcher can't know if the daemon failed (quit) on start-up.
Pre-launch checks include :
Make sure that the configured directories ($log_dir on the server, $fifos on the client, $run_dir on both) exist or can (actually) be created.
In test-mode (option -t
), any created directories are removed.
A failure is a fatal.
Unless in test-mode, make sure that lockfile
$run_dir/server.lck
(or /client.lck
)
can be written and (exclusively) locked. A failure is fatal.
Make sure that the $logfile can be appended ; on failure,
a warning is given and a /tmp/
file is used.
Check that configured hosts are resolvable ($allow_host on the server, $loghost on the client) ; on failure, (only) a warning is given.
On the client it makes sense to continue, even if the $loghost is unreachable, because the daemon will watch the fifo's ; ulities won't block for the lack of a fifo-reader.
In option processing, (only) warnings are issued if spurious options are found.
It is a fatal error to supply an argument which isn't start
or stop
,
or to supply more than one argument.
Commands arlogd-server and arlogd-client set an exit-code.
They may write to stdout
.
Using -s
(for silent) makes them silent.
The exit-code is 0 if
argument start
: a daemon is launched, or was already running.
argument stop
: the daemon is stopped, or wasn't running.
no argument : there is a running daemon.
A running daemon may write to $logfile and syslog.
Events logged in syslog, are also logged in $logfile.
If the daemon can't append to $logfile, it uses some /tmp/
file.
Start/stop events are logged in syslog, as are config- and other startup-errors.
The default install does this :
make directory /etc/arlogd/
unless it exists ;
create (with touch
) an empty file /etc/arlogd/conf
;
create (with touch
) an empty file /etc/arlogd/renames
;
copy the daemon (arlogd.server
or arlogd.client
) to /usr/sbin
;
copy init.d/arlogd-server
(or init.d/arlogd-client
) to /etc/init.d
;
add arlogd as a service with :
chkconfig --add arlogd
/etc/arlogd/conf /etc/arlogd/renames /etc/init.d/arlogd-client /etc/init.d/arlogd-server /var/lock/subsys/arlogd /var/log/arlog/ /var/log/arlogd-save /var/log/arlogd.log /var/log/fifos/ /var/run/arlogd/client.lck /var/run/arlogd/client.pid /var/run/arlogd/client.state /var/run/arlogd/server.lck /var/run/arlogd/server.pid
© 2014-2016
Henk P. Penning,
Faculty of Science,
Utrecht University
42415515133
version arlogd-0.1.8 - Sun Jul 10 07:34:59 2016 UTC - dev revision 188