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

Re: crontab hour range 6-midnight



Jochen Spieker wrote:
> Bob Proulx:
> > Having a literal '~/' in there works for bash.  But it doesn't work
> > for /bin/sh linked to dash for example.
> 
> Works here:
> 
> $ exec /bin/dash
> $ cd /
> $ pwd
> /
> $ cd ~
> $ pwd
> /home/jrschulz

But that doesn't have anything to do with PATH.  You didn't test PATH
containing "~/" in it.  You tested cd with "~" as an option argument.
Those are different things.

If you want to test PATH with "~/" in it then here is a test for it.
It must be two process layers deep.  It must launch a non-bash process
which itself launches a process.  It must not be a bash script.

  $ mkdir -p $HOME/bin

  $ cat >$HOME/bin/pathtrial1 <<\EOF
#!/bin/sh
echo hello from pathtrial1
EOF
  $ chmod a+x $HOME/bin/pathtrial1
  $ pathtrial1
  hello from pathtrial1

  $ cat >$HOME/bin/pathtrial2 <<\EOF
#!/bin/dash
echo "PATH=$PATH"
type pathtrial1
pathtrial1
EOF
  $ chmod a+x $HOME/bin/pathtrial2
  $ pathtrial2
  PATH=/home/rwp/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/sbin:/sbin
  pathtrial1 is /home/bob/bin/pathtrial1
  hello from pathtrial1

That will set up a small test case.  Be sure to quote the EOF and to
check that the variables were not expanded in the test case script and
that the quotes were included properly.  Otherwise they will have been
expanded when you created the script and the test case won't have been
created properly.

Then set up your crontab with PATH holding ~/bin in it as per the
discussion.  Then call pathtrial2 in your crontab.  This following will
do it.

  SHELL=/bin/bash
  PATH=~/bin:/usr/local/bin:/usr/bin:/bin:/usr/games
  * * * * *       pathtrial2

That will show the failure.  Cron will invoke pathtrial2 and since
SHELL is set to bash then bash will find pathtrial2 in $HOME/bin okay.
That first layer of invocation will work successfully.  But the
pathtrial2 script will try to find pathtrial1 on PATH and being a
/bin/dash script it will not interpret PATH with ~/ in it and will
fail to find pathtrial1.  Cron will email the output to you.

  PATH=~/bin:/usr/local/bin:/usr/bin:/bin:/usr/games
  pathtrial1: not found
  /home/rwp/bin/pathtrial2: 4: /home/rwp/bin/pathtrial2: pathtrial1: not found

This illustrates the failure.  It isn't the first shell from cron that
fails.  That shell is bash and it works okay.  It is children
processes of bash that fail since PATH contains ~/ in it and that
expansion is a bash specific extension.

Before someone thinks this is only a problem because /bin/sh is
symlinked to dash let me show an example using perl.  Using perl has
exactly the same problem.  Set up a pathtrial3 script so that it looks
like this:

  #!/usr/bin/perl -l
  print "PATH=$ENV{'PATH'}";
  print "%%>>" . `pathtrial1` . "<<%%";
  print $?;

Run that from the command line with a normal PATH.  You will get this
output:

  $ pathtrial3
  PATH=/home/rwp/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/sbin:/sbin
  %%>>hello from pathtrial1
  <<%%
  0

That looks normal given the script, right?.  Then change the crontab
to call pathtrial3 instead of pathtrial2.  By email you should be
seeing this following output:

  PATH=~/bin:/usr/local/bin:/usr/bin:/bin:/usr/games
  %%>><<%%
  -1

The pathtrial1 script couldn't be found on PATH.  It failed.  It is
this second layer of processes which will fail if they can't find
their programs on PATH.  Perl scripts and other processes that need to
locate programs on PATH will not be expanding ~/ to be the $HOME
directory since that is a bash specific extension.  Those will fail.

Bob

Attachment: signature.asc
Description: Digital signature


Reply to: