4

I know there are a lot of similar question and I've tried lots of things but still can't make it work.

I have cronjob which is scheduled to run on 10min. I can see in /var/log/syslog that it is run normally

Oct 21 07:30:01 stan CRON[7604]: (stan) CMD (stan /home/stan/update.sh)
Oct 21 07:40:01 stan CRON[8304]: (stan) CMD (stan /home/stan/update.sh)
Oct 21 07:50:01 stan CRON[8751]: (stan) CMD (stan /home/stan/update.sh)
Oct 21 08:00:01 stan CRON[9347]: (stan) CMD (stan /home/stan/update.sh)
Oct 21 08:10:01 stan CRON[9789]: (stan) CMD (stan /home/stan/update.sh)

update.sh call php script which update database. When I run directly from terminal the shell script database got updated and it's working perfectly

./update.sh

But from cronjob doesn't update database. My cron

*/10 * * * * stan /home/stan/update.sh

Command produced from shell script is

/usr/bin/php /var/www/html/site/update.php

Permissions of both files

-rwxrwxr-x  1 stan stan    123 Oct 20 15:09 update.sh
-rwxr-xr-x  1 stan www-data 1301 Oct 21 07:52 /var/www/html/site/update.php

Any idea what can be the problem?

Update: PATH

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

update.sh

$ cat update.sh 
#!/bin/sh

list="/var/www/html/site"
config="/usr/bin/php"

for i in "$list"
do
    "$config" "$i"/update.php
done

Reference my question from yesterday which was about the shell and php now is about cron.

$ whereis php

php: /usr/bin/php5.6 /usr/bin/php /usr/lib/php /etc/php /usr/include/php /usr/share/php5.6-intl /usr/share/php7.0-mbstring /usr/share/php7.0-common /usr/share/php5.6-curl /usr/share/php5.6-gd /usr/share/php5.6-mcrypt /usr/share/php5.6-common /usr/share/php5.6-readline /usr/share/php5.6-json /usr/share/php /usr/share/php5.5-mbstring /usr/share/php5.6-opcache /usr/share/php5.6-mbstring /usr/share/php5.6-xml /usr/share/php5.5-common /usr/share/php5.6-mysql /usr/share/man/man1/php.1.gz

$ which php
/usr/bin/php
  • Is this a user crontab, or a file in /etc/cron.d? You appear to be using the format of the latter (with an additional user field) within the former - hence your log shows that it is trying to run a command stan with argument /home/stan/update.sh – steeldriver Oct 21 '16 at 12:34
  • user stan yes. I'm logged with this user $ who -> stan tty7 2016-10-21 06:54 (:0) – S.I. Oct 21 '16 at 12:42
  • So you created the job using crontab -e rather than creating a file in /etc/cron.d? – steeldriver Oct 21 '16 at 12:44
  • Yes, via crontab -e – S.I. Oct 21 '16 at 12:44
  • Well, I've removed stan from crontab -e and seems to work now. Why isn't work with the user? And in this case how can I tell which cron for which user is? – S.I. Oct 21 '16 at 12:54
4

You seem to be confusing two different methods of invoking cron jobs.

Ubuntu inherits from Debian a somewhat confusing policy of supporting both user crontabs that are stored in a spool area /var/spool/cron, and system-wide cron jobs run from /etc/crontab and the files in /etc/cron.d.

Jobs specified in /etc/crontab or via files in /etc/cron.d need an extra field in order to allow them to be run as a different user so the format is something like

*/10 * * * * <username> <command> <args>

Jobs set up via the spool area using crontab -e (or sudo crontab -e for root) already belong to a specific user, and don't need the user field

*/10 * * * * <command> <args>

If you include the username field in a cron job set up via a crontab -e command, it will be misinterpreted as a command: as we can see from your log output,

Oct 21 07:30:01 stan CRON[7604]: (stan) CMD (stan /home/stan/update.sh)

cron is interpreting stan as a command with argument /home/stan/update.sh

The solution should be simply to remove the username stan from your crontab.

  • Thank you for the help and for making clear those two methods. – S.I. Oct 21 '16 at 14:07
2

a few possible problems:

1) You may not have #!/bin/sh as a first line in update.sh

2) PHP may need to execute extra commands but cron jobs are executed without the PATH variable being set. To fix that use echo $PATH on the terminal where the command works and then use export PATH=..., replacing the ... with the output of echo $PATH above

3) PHP may need other environment variables to function. Track them down and export them in update.sh prior to calling /usr/bin/php.

Edit

OK, it isn't 1)

Open a new window (or a new ssh connection) and execute:

for i in `env | sed 's/=.*//'` ; do unset $i ; done

This will unset all environment variables, including the PATH. Then try:

/usr/bin/php /var/www/html/site/update.php

Then post here the error messages.

  • Thanks for the answer. I've updated my question. As you see 1) and 2) are fine. I'm not sure what you mean in 3)? – S.I. Oct 21 '16 at 5:45
  • Just a question before I unset them. I will need to set them again later? And btw why I need to test this since the script is working when I run it directly like this in terminal? – S.I. Oct 21 '16 at 5:58
  • You will unset them just for the current shell session. That is why I asked you to open a new window. Once you are done just type exit, the terminal window will close and everything will be back to normal. – sмurf Oct 21 '16 at 6:02
  • Done. I've unset them. Then executed /usr/bin/php /var/www/html/site/update.php and database got updated. echo $PATH is empty. No errors at all and script is working. – S.I. Oct 21 '16 at 6:04
  • OK, so it is neither 2) nor 3). Your problem is somewhere else and I have no idea where. Sorry. – sмurf Oct 21 '16 at 6:09
2

The problem is the very limited path variable search of crontab. Full path has to be added to add to almost all your commands in all your scripts and subscripts. Or you can add the same search path to the script that you have when running the script manually.

Change from:

#!/bin/sh

list="/var/www/html/site"
config="/usr/bin/php"

for i in "$list"
do
    "$config" "$i"/update.php
done

Change to:

#!/bin/sh

PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

list="/var/www/html/site"
config="/usr/bin/php"

for i in "$list"
do
    "$config" "$i"/update.php
done

Note:

The added path search was taken from what you posted in your question, which work when running the script manually. If you know which path contains the command from the script along with any script or command called by the update.php script, then those are the only search paths that needs to be added.

  • Thanks. Do I need to add PATH in the for now? because still doesn't update database – S.I. Oct 21 '16 at 8:00
  • No. Just add the one line in the change to block. – L. D. James Oct 21 '16 at 8:02
  • Added and cron still run on 10min and still didn't update. I've added what whereis php return in terminal to my question if is in help also... – S.I. Oct 21 '16 at 8:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.