Site icon Leonid Mamchenkov

Working with named pipes in Perl

The collegue of mine came across a problem that developed into an interesting solution that I decided to share with the world. Actually, I think the world is pretty much aware of the solution, but just in case that I will ever be looking for this solution again, I’ll have it handy here.

The task at hand was to do some processing of the logs on the fly. The syslog was configured to filter the appropriate logs into a named pipe and a Perl script was written to read from the said pipe and do all the processing.

The original piece of code looked something like this:

open (SYSLOG, ") {
  do_processing($_);
}

close(SYSLOG);

The problem came with syslog daemon restarts. Every time the syslog was stopped, the EOF was sent to the pipe and the script stopped reading it.

First approach was to nest the pipe reading into an endless loop like this:

while (1) {
  open (SYSLOG, ") {
    do_processing($_);
  }

  close(SYSLOG);
  print "Syslog was restarted\n" if ($debug);
}

While it worked, it wasn’t a very nice looking solution. A couple of alternative ideas that involved signal handling and kill -HUP came around but were also disregarded.

A much better looker approach was found in the book by W. Richard Stevens ” UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications”. The idea is simpe – the same script that opens the named pipe for reading, should open the same pipe for writing. This way, the pipe will stay open as long as the script is working.

The following code works:

open (SYSLOG, "$named_pipe") 
  or die "Couldn't open $named_pipe for writing: $!\n";


while () {
  do_processing($_);
}

close(SYSLOG);

A minor improvement was made after reading perldoc -f open which suggested that the same file can be open for both reading and writing with a single open. Here is the changed code:

open (SYSLOG, "+) {
  do_processing($_);
}

close(SYSLOG);

Simple and elegant – just as code should be.

Drop me a line if you know of any other ways to improve the snippet above.

Exit mobile version