Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cronjob does not execute a script that works fine standalone

I have my php script file in /var/www/html/dbsync/index.php. When cd /var/www/html/dbsync/ and run php index.php it works perfectly.

I want to call PHP file through sh file, the location of SH file is as below

/var/www/html/dbsync/dbsync.sh

This is the content of the dbsync.sh file is:

/usr/bin/php /var/www/html/dbsync/index.php >> /var/www/html/dbsync/myscript.log 2>&1 -q -f

When I cd /var/www/html/dbsync/ and run ./dbsync.sh it works perfectly as well.

Now if I set up crontab as below:

1 * * * * /var/www/html/dbsync/dbsync.sh /var/www/html/dbsync

However, this crontab is not working as expected.

What can be wrong?

like image 303
sanainfotech Avatar asked Apr 27 '16 09:04

sanainfotech


People also ask

Why crontab scripts are not working?

One of the most frequent causes for the crontab job not being correctly executed is that a cronjob does not run under the user's shell environment. Another reason can be – not specifying the absolute path of the commands used in the script.

What should I do to run a script on specific time without cron?

If not using cron, you will have to arrange for the script to re-execute itself at a particular time in the future, maybe using at (which is part of cron), or by sleeping (which would make the executions drift over time), and you would additionally have to set up an initial execution of the script at reboots (again, ...

Does crontab need to be executable?

crontab files have to be regular files or symlinks to regular files, they must not be executable or writable for anyone else but the owner. This requirement can be overridden by using the -p option on the crond command line.


2 Answers

As seen in comments, the problem is that you are not defining what program should be used to execute the script. Take into account that a cronjob is executed in a tiny environment; there, not much can be assumed. This is why we define full paths, etc.

So you need to say something like:

1 * * * * /bin/sh /var/www/html/dbsync/dbsync.sh /var/www/html/dbsync
#         ^^^^^^^

/bin/sh being the binary you want to use to execute the script.

Otherwise, you can set execution permissions to the script and add a shell-script header telling it what interpreter to use:

#!/bin/sh

If you do this, adding the path of the binary is not necessary.

From Troubleshooting common issues with cron jobs:

Using relative paths. If your cron job is executing a script of some kind, you must be sure to use only absolute paths inside that script. For example, if your script is located at /path/to/script.phpand you're trying to open a file called file.php in the same directory, you cannot use a relative path such as fopen(file.php). The file must be called from its absolute path, like this: fopen(/path/to/file.php). This is because cron jobs do not necessarily run from the directory in which the script is located, so all paths must be called specifically.


Also, I understand you want to run this every minute. If so, 1 * * * * won't do. Intead, it will run at every 1st minute past every hour. So if you want to run it every minute, say * * * * *.

like image 178
fedorqui 'SO stop harming' Avatar answered Oct 22 '22 14:10

fedorqui 'SO stop harming'


It is important to understand "login shell" and "interactive shell" what they means.

  • login shell: is briefly when you sign in with ssh session and get a terminal window where you can enter shell commands. After login the system executes some files(.bashrc) and sets some environment variables such as the PATH variable for you.
  • interactive shell :After login on a system, you can startup manually shell terminal(s). The system executes some profile file assigned to your account (.bash_profile, .bash_login,.profile). This files also sets some environment variables and initialize PATH variable for your manually opened shell session.

By OS started shell scripts and cron jobs does not fit in above mentioned way for starting a shell. Therefore no any system scripts(.bashrc) or user profiles are executed. This means our PATH variable is not initialized. Shell commands could not found because PATH variable does not point to right places.

This explains why your script runs successfully if you start it manually but fails when you start it via crontab.

Solution-1: Use absolute path of every shell command instead of only the command name used in your script file(s).

  • instead of "awk" use "/usr/bin/awk"
  • instead of "sed" use "/bin/sed"

Solution-2: Initialize environment variables and especially the PATH variable before executing shell scripts!

like image 5
nix Avatar answered Oct 22 '22 13:10

nix