develooper Front page | perl.perl5.porters | Postings from March 2012

Error handling in one-liners

Thread Next
From:
Christoph Bußenius
Date:
March 25, 2012 02:56
Subject:
Error handling in one-liners
Message ID:
4F6E08E3.8010902@cpan.org
Hi,

let me start with this question:  Does anyone know the difference 
between these two commands:

perl -i -plwe 's/foo/bar/' file
sed -i 's/foo/bar/' file

One hint: Would you use it on a production system?

The difference is how they behave when a write error occurs, like when 
the disk is full.  Perl will silently replace the file with an empty 
file, which is really bad behavior imho.

One might argue that this is not a bug because perl behaves exactly as 
specified in the documentation (perldoc perlrun; perldoc -f print; etc). 
  However when you think about it, many people think of "perl -p" as a 
cooler version of sed and use it the same way.  For instance, if you 
take a Debian system and search the postinst scripts in 
/var/lib/dpkg/info, you will find stuff like this:

(hplib.postinst:)
perl -p -i -e 's:^(\s*ppd=).*$:\1/usr/share/ppd/hplip/HP:' 
/etc/hp/hplip.conf

So what should one do about this?  Either

1) Change perl and the documentation (Don't know how exactly it should 
be changed)
2) Change the one-liners to include proper error handling.  However this 
would really take the brevity out of them, which is probably what most 
script authors value in perl one-liners
3) Use sed instead of perl
4) Ignore the problem / just make sure that your disks don't fill up. 
Actually many people tend to respond this way when I question how stuff 
behaves after write errors (which is why I started this message with 
those silly questions).

Note this does not only affect -i.  There are also scripts like this:

perl -plwe 's/foo/bar/' file > file2 && rm file

This would be the safe version:

perl -plwe 's/foo/bar/; END { close STDOUT or die $! }' file > file2 && 
rm file

Not a real beauty in a shell-script though.  Explicitly closing stdout 
is what most shell tools like sed, sort, etc. do (according to what I 
observed using strace).

In the case of -i, an "END" cannot be used, especially if more than one 
file are specified.

I don't know if this has been discussed before, since I guess things 
have been this way for quite a while.  I could not find anything on 
Google.  If it has, I would like to raise this issue for re-discussion :)

By the way, to actually see the questionable behavior in action, you may 
use the following commands on a Linux system:

mkdir a
sudo mount -o size=1 -t tmpfs tmpfs a
cd a
seq 9999 > file # will write until it fills up
cat file # non-empty output
perl -i -plwe 's/foo/bar/' file # no error
cat file # empty output

Cheers,
Christoph

P.S.: Afaik sed -i is only available in recent GNU sed versions.

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About