<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
Kevin McGregor wrote:
<blockquote cite="midcd5bed5c6b35.45bf5d57@shaw.ca" type="cite">
  <pre wrap="">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 &lt;/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.
  </pre>
</blockquote>
<br>
Regardless of distribution, you can always just call a command from
/etc/rc.local (or something very close to that)...<br>
<br>
However, to ensure it stays running you can take advantage of init(8)'s
functionality and put a line in /etc/inittab(5):<br>
<br>
<b>&nbsp;&nbsp;&nbsp; km:2345:respawn:/usr/local/bin/mypgsqlscript.sh arg1 arg2 argN<br>
</b><br>
...and of course, mypgsqlscript.sh can do anything a shell script can.&nbsp;
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:<br>
<br>
<b>&nbsp;&nbsp;&nbsp; #!/bin/bash<br>
&nbsp;&nbsp;&nbsp; exec /bin/su --login
--command="/usr/local/bin/my_unprivliged_script.sh $@"
some_unprivilged_username<br>
</b><br>
(Psql doesn't usually care who it gets run as, the username is provided
on the command-line... see the one-liner, following:)<br>
<br>
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.<br>
<br>
The other option I would recommend is to look at the "daemontools" or
"mon" packages.&nbsp; They should be available for Ubuntu...<br>
<br>
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?<br>
<br>
Bottom line:&nbsp; you can do this all in one line with inittab(5):<br>
<br>
<b>&nbsp;&nbsp;&nbsp; km:2345:respawn:/usr/bin/psql --dbname syslog --file
/var/run/pgsql.pipe --hostname padsysdb --output
/var/log/pgsql_pipe.out --quiet --username sysloguser<br>
</b><br>
since according to fifo(4) the reading process will block until a
writer connects to the FIFO (aka Named Pipe).&nbsp; Testing reveals that
when the writer close(2)s the FIFO, the reader gets an EOF.&nbsp; The psql
utility's --file option implies that the program will terminate upon
reaching EOF in that file.&nbsp; Then init(8) will restart psql (because of
"respawn") whereupon it will sit and wait for the next (set of)
command(s) to arrive.<br>
<br>
The big thing to watch out for here is timing.&nbsp; 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.&nbsp; 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.<br>
<br>
Also, why would the FIFO vanish?&nbsp; 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<br>
<br>
<b>&nbsp;&nbsp;&nbsp; #!/bin/bash<br>
&nbsp;&nbsp;&nbsp; [[ -p /var/run/pgsql.pipe ]] || /bin/mknod /var/run/pgsql.pipe p<br>
&nbsp;&nbsp;&nbsp; exec </b><b>/usr/bin/psql --dbname syslog --file
/var/run/pgsql.pipe --hostname
padsysdb --output /var/log/pgsql_pipe.out --quiet --username sysloguser<br>
</b><br>
and call that script from inittab instead of psql directly.&nbsp; 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 &lt;/dev/null
2&gt;&amp;1 &gt;/dev/null; [[ -p /var/run/pgsql.pipe]] || mkfifo
/var/run/pgsql.pipe") every 5 minutes.&nbsp; Or put that into inittab, too,
if you only care about it at system startup:<br>
<br>
<b>&nbsp;&nbsp;&nbsp; pp:2345:sysinit:/bin/mknod /var/run/pgsql.pipe p<br>
</b><br>
N.B.&nbsp; "/bin/mknod X p" is exactly equivalent to "/bin/mkfifo X".&nbsp; 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.&nbsp; The joy of backward compatability...<br>
<br>
-Adam Thompson<br>
&nbsp;<a class="moz-txt-link-abbreviated" href="mailto:athompso-muug@athompso.net">athompso-muug@athompso.net</a><br>
<br>
</body>
</html>