how to redirect in bash+crontab

how to redirect in bash+crontab

Oleg Goldshmidt pub at goldshmidt.org
Tue Jul 24 11:52:59 IDT 2012


Hi,

I thought I'd share an observation that was, I admit, new to me - and I
thought I had plenty of experience. And then I have a question or two.

I moved a bunch of scripts to a new computer (RHEL 5.4 -> CentOS 6.2). They
work, but I noticed weird "permission denied" messages in the mails cron
sends. Turns out that I had functions wrapping "real" bash code in progress
messages that produce output like

Doing XYZ ... done [or "Doing XYZ ... failed", or whatever is appropriate]

Since the real output was sometimes redirected to files these messages are
sent to stderr.

Surprise! It all worked for years on RHEL 5.4. On CentOS 6.2, however, it
works flawlessly from the command line, but NOT from crontab! At least
stuff like

echo "fubar" > /dev/stderr

does not. At the same time,

echo "fubar" >&2

works perfectly both interactively and through crontab. [The functional
part of the scripts works fine - the errors come from those progress
messages, but it's immaterial here.]

On RHEL 5.4, CentOS 6.2, and Fedora 15 (my laptop) /dev/stderr is a symlink
to /proc/self/fd/2 (which is what you'd expect). I wrote a little script
that prints "ls -nld" and "ls -nldL" of /proc/self/fd/2 as well as the real
and effective user and group IDs of the process, and ran the script
interactively and from crontab on all three systems. Here is what I
discovered.

RHEL 5.4 (my uid is 500 and my gid is 500, gid 5 is "tty"):
-----------------------------------------------------------------------------------------------

interactive:
lrwx------ 1 500 500 64 Jul 24 10:39 /proc/self/fd/2 -> /dev/pts/1
crw--w---- 1 500 5 136, 1 Jul 24 10:39 /proc/self/fd/2

crontab:
l-wx------ 1 500 500 64 Jul 24 10:40 /proc/self/fd/2 -> pipe:[27443942]
prw------- 1 500 500 0 Jul 24 10:40 /proc/self/fd/2 # [OG] I am the owner!

CentOS 6.2 (my uid is 500, gid is 501, group 5 is "tty" again):
------------------------------------------------------------------------------------------------------

interactive:
lrwx------ 1 500 501 64 Jul 24 10:39 /proc/self/fd/2 -> /dev/pts/0
crw--w---- 1 500 5 136, 0 Jul 24 10:39 /proc/self/fd/2

crontab:
l-wx------ 1 500 501 64 Jul 24 10:27 /proc/self/fd/2 -> pipe:[3750679]
prw------- 1 0 501 0 Jul 24 10:27 /proc/self/fd/2     # [OG] the owner is
root! I can't write to it!

Fedora 15 (my uid is 500, gid is 500, gid 5 is "tty"):
------------------------------------------------------------------------------------

interactive:
lrwx------ 1 500 500 64 Jul 24 11:08 /proc/self/fd/2 -> /dev/pts/2
crw------- 1 500 5 136, 2 Jul 24 11:08 /proc/self/fd/2

crontab:
l-wx------ 1 500 500 64 Jul 24 10:37 /proc/self/fd/2 -> pipe:[47022]
prw------- 1 0 500 0 Jul 24 10:37 /proc/self/fd/2 # [OG] the owner is root!
I can't write to it!

So, when run from crontab stderr is actually a pipe. On RHEL 5.4 the pipe
belongs to the actual user and is writeable. On 6.2 and Fedora the pipe
belongs to root and is not writeable by the user.

When run interactively, stderr is linked to a character device (tty) that
is writeable by the user. For some reason, on Fedora the device is not
writeable by group tty, while on RHEL/CentOS it is.

I think I understand WHAT is happening, e.g., redirecting to /dev/stderr
causes the system to check the file/fifo permissions against the effective
uid and since they are insufficient, fail. At the same time, doing >&2 does
not cause checking filesystem permissions, and hence works. I did strace in
both cases and ">/dev/stderr" does open(2) and then dup2(2), whereas ">&2"
does only dup2(2).

However, I have a lingering feeling that both redirections should work the
same. I expect them to be functionally equivalent (though maybe it's naive
of me). I also do not understand WHY the behaviour changed.

Is it a bug? If so, is it a kernel bug (it creates the /proc hierarchy,
right?) or a cron bug (faulty effective id?) or a bash bug (should
/dev/stderr be handled specially)? Were there (security?) reasons to change
the ownership of the pipe (and permissions on the character tty device in
Fedora, while we are at it)?

Until it is resolved one way or another it looks like ">&2" is much
preferable to ">/dev/stderr". I find it quite unexpected. I actually like
/dev/stderr better since it is less cryptic.

-- 
Oleg Goldshmidt | pub at goldshmidt.org <oleg at goldshmidt.org>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.cs.huji.ac.il/pipermail/linux-il/attachments/20120724/be6dce11/attachment.html>


More information about the Linux-il mailing list