[RndTbl] Scripting question
Adam Thompson
athompso at athompso.net
Tue Jan 30 15:39:58 CST 2007
Kevin McGregor wrote:
> I have this script:
> #!/bin/bash
>
> if [ -e /var/run/pgsql.pipe ]; then
> while [ -e /var/run/pgsql.pipe ]
> do
> psql -q -h padsysdb -U sysloguser syslog </var/run/pgsql.pipe
> done
> fi
>
> ...running on a Ubuntu Linux server. It's clearly very simple; it just keeps checking the named pipe /var/run/pgsql.pipe and sending the contents to the psql command, which interprets the input as a SQL command and executes it accordingly.
>
> My question is, given that I want this loop to execute (a) from server startup (b) indefinitely and without interruption, how do I reasonably ensure (a) and (b)?
>
> More specifically, where do I stick this (or an equivalent) in the startup scripts on Ubuntu, and is there a good automated way to make sure it keeps going? I really don't want to lose any of my database input. It's a fairly critical system, and I'd like to make this pretty robust.
>
Regardless of distribution, you can always just call a command from
/etc/rc.local (or something very close to that)...
However, to ensure it stays running you can take advantage of init(8)'s
functionality and put a line in /etc/inittab(5):
* km:2345:respawn:/usr/local/bin/mypgsqlscript.sh arg1 arg2 argN
*
...and of course, mypgsqlscript.sh can do anything a shell script can.
Keep in mind that init exec(2)'s everything as root, so if you need to
run as a different user you'll need two scripts, where the first script
is a two-liner that looks like:
* #!/bin/bash
exec /bin/su --login
--command="/usr/local/bin/my_unprivliged_script.sh $@"
some_unprivilged_username
*
(Psql doesn't usually care who it gets run as, the username is provided
on the command-line... see the one-liner, following:)
This technique is (almost) distro-independent; the exception being
anything that uses a BSD-style startup sequence where init(8) doesn't
exist... all the major (and all the minor (and almost all of the niche))
Linux distributions use SysV-style init so this will be available to you.
The other option I would recommend is to look at the "daemontools" or
"mon" packages. They should be available for Ubuntu...
The last resort would be to have a script that actually does all the
housekeeping necessary to monitor a daemon-like process and ensure that
it restarts if it dies... but why go to that effort when init(8) does it
for you?
Bottom line: you can do this all in one line with inittab(5):
* km:2345:respawn:/usr/bin/psql --dbname syslog --file
/var/run/pgsql.pipe --hostname padsysdb --output /var/log/pgsql_pipe.out
--quiet --username sysloguser
*
since according to fifo(4) the reading process will block until a writer
connects to the FIFO (aka Named Pipe). Testing reveals that when the
writer close(2)s the FIFO, the reader gets an EOF. The psql utility's
--file option implies that the program will terminate upon reaching EOF
in that file. Then init(8) will restart psql (because of "respawn")
whereupon it will sit and wait for the next (set of) command(s) to arrive.
The big thing to watch out for here is timing. Regardless of which way
it's done, psql probably isn't written to process asynchronous input and
so will probably sit and do nothing until EOF occurs. So if you have a
process writing commands once in a while to the FIFO, you need to ensure
the file descriptor gets closed periodically so that psql can actually
parse the SQL and run it.
Also, why would the FIFO vanish? If there's a real danger of that
happening, wrap the psql command in a shell script and put a mkfifo or
mknod call first
* #!/bin/bash
[[ -p /var/run/pgsql.pipe ]] || /bin/mknod /var/run/pgsql.pipe p
exec **/usr/bin/psql --dbname syslog --file /var/run/pgsql.pipe
--hostname padsysdb --output /var/log/pgsql_pipe.out --quiet --username
sysloguser
*
and call that script from inittab instead of psql directly. You
probably only need/want to account for the possibility of the pipe
vanishing on on end or the other - but you could always create a cron
job that runs that one-liner (/bin/bash -c "exec </dev/null 2>&1
>/dev/null; [[ -p /var/run/pgsql.pipe]] || mkfifo /var/run/pgsql.pipe")
every 5 minutes. Or put that into inittab, too, if you only care about
it at system startup:
* pp:2345:sysinit:/bin/mknod /var/run/pgsql.pipe p
*
N.B. "/bin/mknod X p" is exactly equivalent to "/bin/mkfifo X". Not
sure why the coreutils team decided to duplicate that functionality...
probably because HP/UX or something had a mkfifo command once upon a
time. The joy of backward compatability...
-Adam Thompson
athompso-muug at athompso.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.muug.mb.ca/pipermail/roundtable/attachments/20070130/ab9e0d76/attachment.html
More information about the Roundtable
mailing list