[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: writing to /dev/stdout fails in cron script



Hi

On Fri, Aug 22, 2014 at 11:23:37AM +0200, Tony van der Hoff wrote:
> Hi,
> 
> Running up-to-date Wheezy.
> 
> I have a script, simplified like this:
> 
> -----------------------------
> #!/bin/bash
> DEBUG=1
> 
> OUT=/dev/null
> 
> if [ $DEBUG -ne 0 ]; then
> 	OUT=/dev/stdout
> fi
> 
> echo hello > $OUT
> -----------------------------
> 
> This works fine when invoked from the command line, but when called as a
> cron task, same user, it fails with
> /home/tony/scripts/test: line 10: /dev/stdout: Permission denied
> 
> Any suggestions on how to fix this, please?

Short version: Don't do it. At least not this way.

I suspect that the crontab entry is your own - or alternatively an
/etc/cron.d/* file which specifies a non-root user - is that correct?

If so, the error message makes sense - you have to take into account
how cron works: cron will create an empty temporary file to capture
the stdout/stderr or whatever it runs (because it will be emailed to
you).  And stderr/stdout will be redirected to this file *before* it
drops its privileges.  So this temporary file will be owned by root.
And the permissions on the file ensure it is only writeable by root
(and probably only readable by root, as somebody might expect the
output to be private).

So when your script starts, its stdout has already been opened for
it.  Remember that file permissions are only checked at the time the
file is opened - not subsequently.

But when you come along and do a :
    echo SomeDebug > /dev/stdout

that has to open the file again. Which then fails, because your script
is not root, and the file is only writeable by root.

Try this as an experiment to illustrate the point. Imagine this shell script:


    #!/bin/sh
    # contents of /tmp/somescript
    echo normal echo
    echo bad echo > /tmp/somefile
    echo final echo

and then (as root! - I assume you have sudo installed):

    # umask 077
    # rm /tmp/somefile
    # sudo -u SomeNonRootUser sh /tmp/somescript > /tmp/somefile

and you'll end up with:

/tmp/somescript: 4: /tmp/somescript: cannot create /tmp/somefile: Permission
denied

But the file will contain:
    # cat /tmp/somefile
    normal echo
    final echo

In your case, he solution for switching debugging on/off is probably
changing the way you do things: Instead of writing to /dev/null when
debugging is off, simply do not perform debugging if it is off!
(writing to /dev/null is a waste of resources anyway)

A little shell function like this will do the trick:

debug()
{
  if [ $DEBUG -ne 0 ]; then
    echo "$@"
  fi
}

so you script can use "debug" the same way it uses echo.

Hope this helps.

-- 
Karl E. Jorgensen


Reply to: