I have a cronjob calling a shell script. Inside that shell script and I have these lines:
php backup.php
(cat db-backup.sql ; uuencode db-backup.sql db-backup.sql) | mailx -s 'Database Daily Backup' mail#mail.com
rm -f db-backup.sql
When I run this shell script manually like this ./backup it creates a backup file of database, sends me an email and deletes the file. When cron calls this script It sends me a blank e-mail and it does not call/run the php file properly. What could be the cause of this problem?
Note: both shell script and php file has -rwxr-xr-x perms.
cron is probably not executing the script in a directory where your user account has write permissions. (On my system, ls -l /proc/$(pidof cron)/cwd shows the current working directory is /var/spool/cron/.)
Put an explicit cd /path/to/writable/directory immediately before the php line.
Use full paths when creating cron scripts. For example:
/usr/bin/php-cli backup.php
Related
I have a PHP script that takes about 15 hours to run and I have to run it once a week. The script downloads and extracts the contents of a massive (70gb) CSV file into our database.
I need the script to start running every Sunday at 6 PM and to keep running until it's finished processing the file.
My plan is to create a bash file cron.sh that has the following:
nohup php /var/www/html/cron.php > /var/www/html/outputs/`date "+%Y-%m-%d %H:%M:%S"`.log
And the cron being:
0 18 * * 0 /var/www/html/cron.sh
How would I be able to improve this?
Remember to redirect stderr as well:
nohup php /var/www/html/cron.php > dir/stdout.log 2> dir/stderr.log
or if you prefer to merge them all in the same file:
nohup php /var/www/html/cron.php > dir/stdout.log 2>&1
The 2>&1 means redirect stderr to the same file stdout is using.
The rest is all fine, putting the command inside a shell script makes it more readable if the line is too long. Also if you later want to make the task do more things, it is easier to update the script file.
I would probably rename the cron.sh file to something more meaningful.
Since your OP asked "How would I be able to improve this" -- You didn't mention if you HAD to use PHP.
If the CSV is that large .. I would create a bash file that does the same thing that your PHP file does (since you're already calling cron.sh). You would have to change your PHP configuration to less than ideal settings to be able to run it efficiently. IMHO straight bash is the way to go. That way nohup can be bypassed entirely.
Meaning I would:
1) Create a login path for MySQL to securely connect to your db from the .sh file. You can acheive this with the following command:
sudo mysql_config_editor set --login-path=client --host=yourHost --user=MySQL_user --password
You will be prompted for the MySQL password.
2) Once that is done, you can access MySQL in your bash file like such AND create your logs all in the same file:
#!/bin/bash
cd /place/where/you/want/the/csv/
wget http://your_file_location.com/csv/location/file.csv
# Or whatever you're doing to "download" it -- Just an example ..
mysql --login-path=local infile=1 3parsfdb -e "LOAD DATA LOCAL INFILE 'file.csv' INTO TABLE your_table FIELDS TERMINATED BY ','"
echo "Whatever you've collected" >> /var/www/html/outputs/`date "+%Y-%m-%d %H:%M:%S"`.log
Of course that's just an example .. But you get the general idea. Then store said bash file in a safe location.
3) Put your newly created bash file into the crontab. You can use your user's crontab, or if the user doesn't have access to the bash file or directory you put it in, you can use root's crontab -- IE:
0 18 * * 0 /path/to/your/bash/file/BackupCSVToDB.sh
The saved overhead of not having to use PHP could save the run-time literally hours.
I have a ridiculously simple shell script, nothing more than a few instructions to run some php files ...
#!/bin/bash
clear
cd /home/************** // Just for privacy here
php cron-cpt.php
php cron-lvt.php
php cron-plots.php
php cron-m.php
php cron-a.php
The script is called metrics.sh which is chmod'd and just sits in my local binary folder.
If I run the script from the command line, it works perfectly.
If I add the same script to the cron tab to run once a day, it runs over and over. I assumed the cron was the same as invoking it manually from the command line?
I'm using the same user to invoke in cron as logged on cmd line and have tried as root and a standard user, but the same results prevail.
Google has not been helpful with this. Any suggestions?
Add this to your cronTabs:
0 1 * * * /home/metrics.sh
Change the location to your metrics.sh's location.
I have an Amazon EC2 instance (Ubuntu Server 13.04 - 64 bit [ami-bf1d8a8f]) running my website. I need to setup a Cron Job to get an email alert everyday.
Does anyone have any advise or possible solutions?
Thanks for your time.
It's just the same as setting up a cron job on any other server via command line.
Connect via SSH
Navigate to /etc/cron.daily
Make a new script that runs / calls a PHP script to send the email/other tasks
Make sure its executable
You can use a command such as wget -q -O temp.txt http://www.site.com/cron.php to call the PHP script, or via command line php /var/www/site/cron.php.
Regarding the wget method, temp.txt will contain the output of the script, or you can redirect the output to /dev/null. This will just discard all output. If you need to save the output of the cron script and you decided to go with the command line method then you can output the data to a file php /var/www/site/cron.php > output.txt
If you need more explanation/detail post a comment. Also take a look at Basic cron job set up to execute php file daily
Step 1: Create a bash script in the cron.daily folder
Connect to the instance via SSH, navigate to the daily cron folder with cd /etc/cron.daily. Next type sudo nano mailscript, notice there is no .sh bash extension. I had a problem with the extension which caused the script to not run.
Step 2: Bash script contents
Enter this into the command line text editor nano
#!/bin/bash
php /var/www/mail-script.php > /var/www/mail-script-log.txt
Now save the text file and exit, to save use CTRL + O and then press enter, to exit press CTRL + X.
Step 3: Make it executable
We need to allow the file to be executed, type sudo chmod +x mailscript.
Step 4: Try it out
To test it out type ./mailscript to run the cron in cron.daily. Now check your emails!
I would like to execute a cronjob for a routine task every X hours. The cronjob basically executes a shell script which in turn uses a WGET command to download files from a remote server. However, before I run this shell script I want the cronjob to execute a php script which will check whether the update's available (there's no point in wasting BW and downloading the same file over and over again) and if it is, it should pass on the update URL to the shell script which in turn uses the WGET command.
The cronjobs are set from the hosts Admin Panel. There is no other way around it. Being a shared hosting service, I am not allowed access to other functions on PHP which might do the task for me either.
Is this possible? I am Linux illiterate. I have installed a few RPM's on Fedora but that's about it. Please bear with me. Thanks!
Just pass --timestamping to your wget command.
Alternatively if you are more familiar with PHP's ways you can check this question for a usable method.
Use a curl HEAD request to get the file's headers and parse out the Last-Modified: header.
To use a php script as a regular command line executable use this as a starting point:
#!/bin/env php
<?php
echo "Hello World\n";
Save the file without the .php and tuck it somewhere that your server won't serve it.
Next, set the executable bit so that you can execute the script like a regular program
(u+x in the following command means grant the [u]ser e[x]ecute privileges for helloworld, and chmod is the command that unix variants use to set file permissions)
Omit the $ in the following sequence, as it represents the command prompt
$ chmod u+x helloworld
now you can execute your commandline script by calling it in the bash prompt:
$ ls
helloworld
$ ./helloworld
Hello World
$
From here you can get the full path of the executable script:
$ readlink -f helloworld
/home/SPI/helloworld
And now you can install the cronjob using the path to your executable script.
i want to execute a php script every day. i have a bash script containing below lines. and i was doing it with that script. but by this way, it can be executed from another computer. lets say webservername="slmnbr" any body can call myscript with
xhttp://slmnbr/myscript.php.
i want to call it from just server.
BASE_URL=http://`get-webservername`
/usr/bin/wget --no-check-certificate --timeout=0 -O - "$BASE_URL/myscript.php"
thanks in advance
You need to have PHP CLI (command line interface) to do this. It often comes with the PHP installation package (or a separate package).
So as #James mentioned it you need to precede you script name with the CLI PHP executable which in windows is php.exe somewhere in your install directory.
In UN*X systems it's somewhere in /usr/bin or /usr/local/bin or /opt/local/bin. If it is in the PATH you can simply execute it like this:
php your_script.php
But keep in mind that running your script from server will be not the same as running from a webserver. For e.g. you won't have the POST or GET variables. So your script may not work.
Update
You can make the cron ran scripts unreachable for your webserver by making it unreadable by the user who is running the PHP scripts by the http daemon (usually www-data).
I recommend to make it readable only by the user who is running it from cron:
chown cronuser your_script.php
chmod 0400 your_script.php
Update2
If you're running your script in cron with the same user as the webserver does, then at the top of your script stop it from being executed:
if (!(php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']))) {
header('HTTP/1.1 403 Forbidden');
exit;
}
To execute a task(or a php script) every day use cron.
The link has all the info you need, including how to prevent external access.
With any recent version of "php" you should get a standalone executable called:
"php.exe"
Just execute this like so:
/usr/local/php.exe your_script.php