Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux crontab 定時執行 PHP 程式正確姿勢:Shebang、CLI 模式、環境變數與常見坑點

編輯:Linux 教學

在 Linux 透過 crontab 定時執行 PHP 腳本看似簡單,實則暗藏環境變數缺失、工作目錄錯誤、PHP CLI vs FPM 差異、輸出重導向、執行超時等坑點。本文詳細說明正確寫法:#!/usr/bin/php shebang、完整路徑呼叫、載入 .env 設定、鎖檔防重複執行、日誌輪轉、systemd timer 現代替代方案。

一、核心原則:PHP 腳本必須具備 CLI 獨立執行能力


#!/usr/bin/php

二、crontab 寫法三種等效形式

形式範例優缺點
直接呼叫 PHP 二進制*/5 * * * * /usr/bin/php /opt/scripts/job.php >> /var/log/job.log 2>&1明確、不依賴 shebang、推薦生產環境
利用 shebang 直接執行*/5 * * * * /opt/scripts/job.php >> /var/log/job.log 2>&1簡潔、需 chmod +x 且 shebang 正確
系統 crontab (/etc/crontab) 指定用戶*/5 * * * * www-data /usr/bin/php /opt/scripts/job.php >> /var/log/job.log 2>&1集中管理、可指定執行身分

三、環境變數陷阱與解決

cron 執行環境極度精簡:PATH=/usr/bin:/bin、無 HOME、無 LANG、無專案專用變數。

解決方案 A:腳本內 putenv() 載入 .env (推薦)


// 見上方核心原則第 2 點

解決方案 B:crontab 行首宣告


PATH=/usr/local/bin:/usr/bin:/bin
LANG=zh_TW.UTF-8
APP_ENV=production
*/5 * * * * /usr/bin/php /opt/scripts/job.php

解決方案 C:包裝器腳本


#!/bin/bash
# /opt/scripts/run_job.sh
export APP_ENV=production
export LANG=zh_TW.UTF-8
cd /opt/scripts
/usr/bin/php job.php >> /var/log/job.log 2>&1

crontab 僅呼叫 /opt/scripts/run_job.sh。

四、常見坑點排查表

現象原因解決
手動執行正常,cron 不執行環境變數/工作目錄/權限不同腳本加 chdir(dirname(__FILE__))、完整路徑、載入 .env
PHP Warning: Module 'xxx' already loadedcli/php.ini 重複載入擴充檢查 /etc/php/7.x/cli/conf.d/ 去重
資料庫連線失敗PDO DSN 用 localhost → Unix socket,cron 環境無 socket改用 127.0.0.1 或指定 unix_socket=/var/run/mysqld/mysqld.sock
輸出亂碼/中文問號LANG 未設定export LANG=zh_TW.UTF-8
腳本重複執行上次未結束,cron 再次觸發flock 鎖檔 (見核心原則第 4 點)
執行超時被 killcron 無內建超時,但系統可能有限制set_time_limit()、或用 timeout 300 包裝
日誌檔案過大無輪轉配置 logrotate 或用 rotatelogs

五、現代替代:systemd Timer (精確到秒、支援依賴、日誌整合)


# /etc/systemd/system/php-job.service
[Unit]
Description=PHP Scheduled Job
After=network.target mysql.service

[Service]
Type=oneshot
User=www-data
WorkingDirectory=/opt/scripts
ExecStart=/usr/bin/php job.php
StandardOutput=append:/var/log/php-job.log
StandardError=append:/var/log/php-job-error.log

# /etc/systemd/system/php-job.timer
[Unit]
Description=Run PHP Job every 5 minutes

[Timer]
OnBootSec=5min
OnUnitActiveSec=5min
AccuracySec=1s
Persistent=true

[Install]
WantedBy=timers.target

啟用:systemctl daemon-reload && systemctl enable --now php-job.timer

優點:秒級精度、 journald 整合、依賴管理、隨機延遲 RandomizedDelaySec 避免驚群。

六、日誌輪轉配置 (logrotate)


/var/log/php-job.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 640 www-data www-data
    sharedscripts
    postrotate
        systemctl reload php-job > /dev/null 2>&1 || true
    endscript
}
Copyright © Windows教程網 All Rights Reserved