how to redirect in bash+crontab

how to redirect in bash+crontab

Nadav Har'El nyh at math.technion.ac.il
Wed Jul 25 07:33:36 IDT 2012


On Wed, Jul 25, 2012, Oleg Goldshmidt wrote about "Re: how to redirect in bash+crontab":
> While there are, indeed, many ways to acquire a fd the "normal" case,
> e.g., for
> 
> echo "fubar" > $HOME/tmp/myfakestdout

But this is NOT your use case!

In your use case you did

	echo fubar > /dev/stderr

not to a specific file. I'm not suggesting you should change it to a
specific file. However, what I *am* suggesting, is that this /dev/stderr
may actually point not to a pipe or terminal, but to a file. I.e., your
parent process redirected standard error to a file. In that case, your
/dev/stderr will be a symlink to an ordinary file - with its ordinary
owner and permission - not to a fake "pipe" file like you saw.

> > Like I explained, they *can't* be done right (when right mean "just
> > like dup(2) would work) when it comes to ordinary files (not pipes).
> >
> > The only way to do this right, as far as I can see, is for
> > /dev/stderr and friends *not* to be symbolic links.
> 
> Sorry, I don't really see what symlinks have to do with it. I think
> /dev/stderr and friends have been symlinks since forever (even Stevens
> says so, and, sadly, he passed away years ago), and everything worked

Forever is a relative term ;-) I didn't look at Stevens, but unless I
remember wrong (and it's completely possible), /dev/fd/2 is only a link
on *Linux*, and wasn't a symlink on any other Unix variant - including
Solaris to which I had acess to just a few years ago (and sadly, no
more).

I don't know why, according to your experiments, the owner of that fake
"pipe" file were changed recently. I don't know if this change makes any
sense. But what I'm trying to say is that even if they didn't change
this, you could have had exactly the same problem if your parent process
redirected your standard error to a file, rather than a pipe.

> just fine when
> 
> * /dev/stderr was a symlink to /dev/fd/2

This is of course fine. This intermediate symlink is not your problem.

> * /dev/stderr is a symlink to a tty character device
> * /dev/stderr was a symlink to a pipe with appropiate ownership

Do you agree that /dev/stderr is not *always* a symlink to a *pipe*?
It is only a symlink to a pipe in your specific example, because the
parent process redirected your stderr to a pipe. It could have
redirected your stderr to anything else - a terminal, a pipe, etc.
The permission change which you noticed with the pipes, while very
strange (and indeed deserving explanation... did you look at the code?) 
is only part of the bigger problem.

> I think the "symlink" and "pipe" parts are irrelevant, as is the
> "using open()" part - these are just implementation details. After
> all, even for the good old /dev/fd/2 there was an open() call, the
> special implementation part was that the mode argument was ignored.

Right - for devices, open() is done specially. For symlinks it can't.

> Incidentally, if I read Stevens right this had nothing to do with bash
> - the behaviour would be the same if you opened /dev/fd/* in your
> own code as well. Or if you opened /dev/stderr in your own code. As
> far as I understand this special treatment was built into open(2).

Not into open(2), but rather into the device driver. Each device driver
implements open() its own way.

> I didn't immediately see anything special in the logic of, say,
> do_filp_open() in the kernel's fs/namei.c. As far as I could see
> symlinks are followed unil resolved (the branch labeled "do_link") and
> then the real work is done (the "do_last" label). At some point there
> is a check for special_file (in do_dentry_open() in fs/open.c) but
> this checks whether the file is a character device or a block device
> or a pipe or a socket and seems intended for some sort of bookkeeping
> rather than actively ignoring the mode (which would not sound
> logical). Not sure - too tired.

There's no relation between the "mode" (which is basically - whether you
wanted to open the file for reading and writing) and permission check
(owner, group, etc.). Permission check was also done on /dev/fd/2
when it was a character device, but it will always succeed because this
file was simply created world-readable and world-writable. Opening it
would never fail because of permission problems, because it shouldn't
just like dup() never fails on permission problems.

> I am inclined to suspect that the pipe that the kernel creates has
> wrong ownership/permissions, and if/when that is fixed everything will
> be sane again.

Unless crontab starts directing stderr to /var/log/messages or something
instead of a pipe :-)

-- 
Nadav Har'El                        |        Wednesday, Jul 25 2012, 6 Av 5772
nyh at math.technion.ac.il             |-----------------------------------------
Phone +972-523-790466, ICQ 13349191 |Time is the best teacher. Unfortunately
http://nadav.harel.org.il           |it kills all its students.



More information about the Linux-il mailing list