2007-01-14
An alarming reflex in my use of find
It makes me nervous that my fingers appear to feel that the right
thing to type after 'find . type f -print |' is 'xargs rm -f'.
Sometimes they're quite insistent about it.
I am not sure where this reflex comes from, because I don't think
I've done that particular operation that many times. It certainly
makes typing 'for all files' find operations a twitchy exercise, and
I get to worry that someday I will, eg, accidentally delete all of
WanderingThoughts instead of counting how many entries it has.
(Possibly I should deal with this by putting the find bit into a
script I call allfiles or something, so I wouldn't be typing something
that cues my reflexes. On the other hand, this is a reflex I should
probably stamp out as fast as possible, so maybe I shouldn't.)
2007-01-11
An interesting Bourne shell limitation
Presented in illustrated form, on at least Solaris 8, FreeBSD, and OpenBSD:
$ exec 9>/dev/null $ exec 10>/dev/null exec: 10: not found
(And the shell exits.)
The genuine Bourne shell only allows redirection to (or from)
single-digit file descriptors; if you give multiple digits, it
instead gets parsed as 'exec 10 >/dev/null'.
(The limitation has been faithfully copied by at least some Bourne shell reimplementations and was retained in ksh, but bash has dispensed with it, so you won't see this behavior on (most) Linux machines.)
This limitation is implicitly in the V7 sh manpage, which says about redirection:
If one of the above is preceded by a digit then the file descriptor created is that specified by the digit (instead of the default 0 or 1).
In the grand tradition of reading Unix manpages, using the singular 'digit' means that multiple ones aren't allowed.
This wording was carried on into the Solaris sh manpage, but not the
FreeBSD one. The FreeBSD situation is interesting, since I believe the
FreeBSD shell was rewritten from scratch; clearly the people doing the
rewrite knew about (and decided to preserve) the limitation, but then
they didn't document it.
(One might argue that the FreeBSD usage of '[n]> file' in the manpage
implies that 'n' can only be a single digit, but I think that the ice
is thin, if only because they use things like '[n1]<&n2'.)
2007-01-10
A gotcha with inetd/xinetd and popular UDP services
We have historically had a small problem with our inetds: every so
often when we attempted to restart it with a SIGHUP to make it pick up a
configuration change, it would fail to bring up an important UDP-based
service we need, reporting a failure to bind to the UDP port.
(We saw the same problem with xinetd; I'm using 'inetd' as as a
generic term.)
What was probably happening is that when this would happen, inetd had
just spawned the program to handle the service and it was still running
when inetd itself was restarting. As part of restarting, most versions
of inetd close each TCP or UDP port they were listening on and then
reopen and rebind it. (Technically inetd closes the file descriptors
that are the listening server sockets.)
For TCP-based services that are running at the time, this is no problem.
When inetd spawns a program to handle a TCP service the program is
handed a connected socket, which we can label as '(dest-ip, dest-port,
my-ip, my-tcp-port)', which does not conflict with inetd re-binding
to the listening TCP port, '(*, *, *, my-tcp-port)'.
But UDP-based services are different. Because UDP is connectionless,
the only thing inetd can give to programs that it starts to handle
UDP services is a full copy of its own listening socket, ie
'(*, *, *, my-udp-port)'. So when inetd attempts to re-bind
a new listening UDP port, it is trying to recreate '(*, *, *,
my-udp-port)' and the kernel refuses because it already has one
of those around and it can't have a second (for sensible reasons).
We ran into the problem often enough to be problematic because this UDP
service was reasonably frequently used (most UDP services that people
have inetd handle are only infrequently used; people tend to make
frequently used UDP stuff into actual daemons).
(Because some of the SIGHUP restarts were automatic, it's not quite
good enough to SIGHUP inetd repeatedly until it came up right; one
would have to write the auto-restart script so that it knew when the
UDP port was supposed to be bound to start with and when it wasn't.)