Cronjob & Crontab với PHP

1. Cronjob là gì? Hiểu một cách ngắn gọn là : Cronjob là tập các tác vụ cho phép thực hiện một hoặc số đoạn mã tự động theo một lịch trình đã được lập lịch sẵn và nó cứ liên tục, liện tục chạy ở chế độ nền của hệ thống. Thực chất Cronjob là một file chứa đựng lịch biểu (schedule) của các được ...

1. Cronjob là gì?

Hiểu một cách ngắn gọn là: Cronjob là tập các tác vụ cho phép thực hiện một hoặc số đoạn mã tự động theo một lịch trình đã được lập lịch sẵn và nó cứ liên tục, liện tục chạy ở chế độ nền của hệ thống. Thực chất Cronjob là một file chứa đựng lịch biểu (schedule) của các được tập lệnh cần chạy.

Ví dụ: Đôi khi bạn cần chạy Cron để gửi E-Mail chúc mừng những người đăng ký vào lúc 12h:00 PM mỗi ngày thứ 7. Hoặc bạn cần chạy Cron để tự động backups dữ liệu của Server vào lúc 23.59 hàng ngày. Có nghĩa là cứ tới chủ nhật hoặc cứ tới thời điểm 23:59 là hệ thống nó automatic thực hiện mà bạn không cần làm gì hay kích hoạt gì.

2. Cronjob làm việc thế nào?

Cronjob thực chất là một lện Linux để nên kế hoạc thực hiện nhiệm vụ nào đó tiếp theo. Một Cronjob Schedule đơn giản chỉ là một file text. Mỗi một người dùng có một Cronjonb Schedule riêng, File này thường nằm ở trong thư mục cron với đường dẫn /var/spool/cron. Cronjob files không cho phép bạn tạo hoặc chỉnh sửa trực tiếp với bất kỳ trình soạn thảo Text Editor nào, trừ khi bạn dùng lệnh Crontab ở phía Server.

Một số lệnh thường dùng:

crontab -e: Chỉnh sửa file Crontab 
crontab -l: Hiển thị danh sách Crontab 
crontab -r: Xóa Crontab
crontab -r: Xóa Crontab nhưng yêu cầu bạn confirm

Hầu hết tất cả Server đều được cài đặt sẵn Crontab, tuy nhiên vẫn có trường hợp Server không có. Nếu bạn sử dụng lệnh Crontab -l mà thấy output trả lại -bash: crontab: command not found thì cần tự cài crontab thủ công.

3. Cấu trúc của crontab

Một Crontab file có 5 trường xác định thời gian, cuối cùng là lệnh sẽ được chạy định kỳ, cấu trúc như sau:

*     *     *     *     *     command to be executed
-     -     -     -     -
|     |     |     |     |
|     |     |     |     +----- day of week (0 - 6) (Sunday=0)
|     |     |     +------- month (1 - 12)
|     |     +--------- day of month (1 - 31)
|     +----------- hour (0 - 23)
+------------- min (0 - 59)

Trong đó:

*: Có nghĩa là tác vụ sau đó sẽ được chạy ở mọi giá trị cho cột đó.

Để có thể hiểu hơn về Cronjob chúng ta sẽ có một ví dụ như sau:

Ví dụ 01: Thực hiện tác vụ gửi thư cho một địa chỉ email bất kỳ vào mỗi thứ 7.

Ta có một file PHP script như sau /var/www/html/cron/mail.php

<?php
	// the message
	$msg = "FILE này sẽ được thực thi vào mỗi thứ 7 vào lúc 12:10 PM.";
	// send email
	mail("someone@gmail.com","Cron Job",$msg);
?>

Ta có lệnh Crontab như sau:

10 12 * * 6 /usr/bin/php /var/www/html/cron/mail.php

Tiếp theo mình sẽ đưa ra các thời điểm khác nhau để chạy lệnh Crontab.

  • Cronjob sẽ chạy mọi lúc, mọi thời điểm.
* * * * * /usr/bin/php /var/www/html/cron/mail.php
  • Cronjob sẽ chạy mọi lúc 0 phút(Hết 60s chạy một lần)
0 * * * * /usr/bin/php /var/www/html/cron/mail.php
  • Cronjob sẽ chạy mọi lúc 15 phút (1h:15,2h:25, 3h:15...vvvv)
15 * * * * /usr/bin/php /var/www/html/cron/mail.php
  • Cronjob sẽ chạy mọi lúc 2h:30 phút (2h:30 01/01/2017,2h:30 02/01/2017..vv)
30 2 * * * /usr/bin/php /var/www/html/cron/mail.php
  • Cronjob sẽ chạy vào 2h:30 phút ngày 15 hàng tháng
30 2 15 * * /usr/bin/php /var/www/html/cron/mail.php
  • Cronjob sẽ chạy vào lúc 12h:30 các ngày 2,3,5 hàng tháng.
30 12 2,3,5 * * /usr/bin/php /var/www/html/cron/mail.php
  • Cronjob sẽ chạy vào lúc 12h:30 từ ngày 1->5 hàng tháng.
30 12 1-5 * * /usr/bin/php /var/www/html/cron/mail.php
  • Cronjob sẽ chạy 2 ngày một lần.
* * */2 * * /usr/bin/php /var/www/html/cron/mail.php
  • Cronjob sẽ chạy 5 giờ một lần.
* */5 * * * /usr/bin/php /var/www/html/cron/mail.php

Lưu ý: /usr/bin/php xác định souce code của bạn chạy bằng ngôn ngữ gì? ở ví dụ là mình sử dụng PHP 

4. Xác định Command line.

Để khởi chạy một command line Cronjob thông thường sử dụng một trong hai phương pháp sau.

  • Thực hiện các tập lệnh bằng cách sử dụng php từ crontab

Sử dụng php để thực thi và gọi script php từ crontab. Ví dụ sau đây sẽ thực thi myscript.php sau mỗi giờ.

# crontab -e
00 * * * * /usr/bin/php /home/john/myscript.php
  • Chạy tập lệnh php sử dụng URL từ crontab

Nếu tập lệnh PHP của bạn có thể được gọi bằng một URL, bạn có thể sử dụng lynx(Trình duyệt chỉ có văn bản | xem), curl, hoặc wget để thiết lập một crontab.

P/s: Nói một cách dễ hiểu nhất thì cả ba lệnh lynx, curl, wget đều là các lệnh của Linux giúp cho bạn thao tác với tệp tin. Trong đó lynx & wget được sử dụng để tải các tệp tin trên internet và curl được sử dụng để lưu dữ liệu tải vào tệp tin. Các bạn có thể tìm hiểu thêm tại đây.

  • Curl: http://www.justpassion.net/tech/programming/bash-shell/lenh-curl-trong-linux-2.html
  • Wget: http://www.justpassion.net/tech/programming/bash-shell/lenh-wget-trong-linux.html

Mình lấy ví dụ một đoạn php script sau nó sẽ thực thi tệp lệnh PHP sau mỗi giờ bằng cách gọi URL từ Lynx. Mặc định Lynx sẽ mở URL này ở chế độ tương tác với người dùng. Tuy nhiên bạn có thể sử dụng tùy chọn -dump trong tệp lệnh của Lynx để xuất đầu ra của URL này tới một đầu ra tiêu chuẩn.

00 * * * * lynx -dump http://www.chiasephp.net/myscript.php

Bạn theo dõi tiếp dòng lệnh sau đây sẽ thực thi tệp lệnh PHP sau mỗi 5 phút bằng cách gọi URL sử dụng curl. Mặc định curl sẽ hiển thị đầu ra ở đầu ra tiêu chuẩn(Không xuất ra cái gì cả). Bằng việc sử dụng tùy chọn curl - o bạn có thể xuất đầu ra của tệp script đó tới một fle tạm nào đó e.g temp.txt

*/5 * * * * /usr/bin/curl -o temp.txt http://www.chiasephp.net/myscript.php

Cuối cùng dòng lệnh sau sẽ thực thi tệp lệnh PHP sau mỗi 10 phút bằng cách gọi tới URL sử dụng wget. Tuy chọn -q  cho biết chế độ im lặng. -o temp.txt chỉ ra rằng đầu ra sẽ được lưu vào file tạm.

*/10 * * * * /usr/bin/wget -q -O temp.txt http://www.chiasephp.net/myscript.php

5.Disable Email

Mặc định Cronjob sau khi thực hiện xong một tác vụ sẽ tự động gửi email tới một tài khoản được thiết lập. Nếu bạn không thấy cần thiết thì có thể sử dụng lệnh sau để loại bỏ tùy chọn này.

>/dev/null 2>&1

6. Tạo tệp Log

30 18 * * * rm /home/someuser/tmp/* > /home/someuser/cronlogs/crontabs.log

7. MAILTO

Nếu bạn muốn gửi kết quả của cronjob tới người khác bạn có thể làm như sau.

cmd | mail -s "Tiêu đề email" user

8. Cronjob với PHP

Trong một số trường hợp bạn không có quyền truy cập vào Server SSH hoặc Server Hosting để có thể tạo các Cronjob.

Hoặc bạn tạo một công cụ từ Admin cho phép khách hàng active các Cronjob mà bạn đã được thiết kế sẵn. Thật may mắn PHP cho phép bạn làm được tất cả công việc này & bạn có thể follow theo ví dụ sau đây.

Ví dụ: Setup một cronjob sau mỗi 5 phút.

// Hiện thị danh sách cronjob
$output = shell_exec('crontab -l');

// Cronjob File
$cron_file = "/tmp/crontab.txt";

// Command
$cmd = "5 * * * * wget -O /dev/null http://www.chiasephp.net/cron.php >/dev/null 2>&1";
file_put_contents($cron_file, $output.$cmd.PHP_EOL);

// Thực hiện Cronjob
exec("crontab $cron_file");

Trong CMS của mình thì mình xây dựng thành một class có các function như sau:

  • create($cmd): Tạo mới một cronjob.
  • update($cmd): Cập nhật một cronjob
  • exists($cmd): Kiểm tra sự tồn tại của một cronjob.
  • delete($cmd): Xóa một cronjob.

Hàm exists($cmd):

function exists($cmd){
	$cronjob_exists=false;
	
	@exec('crontab -l', $crontab);
	
	if(isset($crontab)&&is_array($crontab)){
		$crontab = array_flip($crontab);
		if(isset($crontab[$cmd])){
			$cronjob_exists=true;
		}
	}
	return $cronjob_exists;
}
  • Hàm delete($cmd)
function delete($command){
	@exec('crontab -l', $crontab);
	//Find command
	if(is_array($crontab)){
		$key = array_search($cmd, $crontab);
		unset($crontab[$key]);
	}
	$cron_file = "/tmp/crontab.txt";
	@file_put_contents($cron_file, implode(PHP_EOL,$crontab));
	@exec("crontab $cron_file");
}

P/s: Các hàm create và update các bạn tự viết dựa vào đoạn code phía trên nhé.

9. Tổng kết

Như vậy mình đã trình bày với các bạn về cronjob. Mong rằng bài viết ngắn này có thể phần nào đó sẽ giúp bạn củng cố kiến thức về Cronjob nhé.

0