高並發站點若使用默認文件存儲,/tmp 會積累海量 sess_* 文件,導致 inode 耗盡、ls 卡頓、備份緩慢。本文提供生產級解決方案:多級散列目錄 + 專用清理腳本 + Cron 定時任務。
; php.ini session.save_path = "2;/var/lib/php/session" ; 含義:2 級子目錄,根目錄 /var/lib/php/session ; 實際路徑示例:/var/lib/php/session/a/b/sess_xxx ; 總目錄數 = 36^2 = 1296,極大緩解單目錄壓力
#!/bin/bash
# 版本 1.0
# 作者: 運維團隊
# 用途: 初始化 PHP Session 多級目錄結構並設置權限
SESSION_ROOT="/var/lib/php/session"
LEVEL=2
USER="www-data"
GROUP="www-data"
# 創建 36x36 兩級目錄 (0-9, a-z)
chars=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z)
for c1 in "${chars[@]}"; do
for c2 in "${chars[@]}"; do
mkdir -p "${SESSION_ROOT}/${c1}/${c2}"
done
done
# 設置擁有者與粘滯位 (防止非擁有者刪除)
chown -R "${USER}:${GROUP}" "${SESSION_ROOT}"
chmod -R 1777 "${SESSION_ROOT}"
echo "Session 目錄初始化完成: ${SESSION_ROOT}"
# 自動修改 php.ini (可選)
PHP_INI="/usr/local/php/lib/php.ini"
if grep -q '^;session.save_path = "/tmp"' "$PHP_INI"; then
sed -i 's#^;session.save_path = "/tmp"#session.save_path = "2;/var/lib/php/session"#' "$PHP_INI"
echo "php.ini 已更新,請重啟 PHP-FPM 生效"
fi
#!/bin/bash
# 版本 1.0
# 作用: 清理超過指定時間未訪問的 Session 文件
# 佈署: 放入 /usr/local/sbin/clean_session.sh,chmod +x
SESSION_ROOT="/var/lib/php/session"
MAX_AGE_MIN=180 # 3 小時未訪問視為過期 (對應 session.gc_maxlifetime=10800)
# 使用 find 刪除,-amin 訪問時間,-delete 直接刪除
find "${SESSION_ROOT}" -type f -amin +${MAX_AGE_MIN} -delete
# 可選: 刪除空目錄
find "${SESSION_ROOT}" -type d -empty -delete
logger "PHP Session 清理完成,閾值 ${MAX_AGE_MIN} 分鐘"
# /etc/cron.d/php-session-clean # 每小時第 5 分執行清理 5 * * * * root /usr/local/sbin/clean_session.sh >> /var/log/php_session_clean.log 2>&1 # 或編輯 root crontab # crontab -e # 5 * * * * /usr/local/sbin/clean_session.sh
# 檢查文件數量 find /var/lib/php/session -type f | wc -l # 檢查 inode 使用 df -i /var/lib/php/session # 監控腳本執行日誌 tail -f /var/log/php_session_clean.log
文件存儲存在單機瓶頸、多機同步難、清理麻煩。生產環境強烈建議遷移至 Redis:
; php.ini session.save_handler = redis session.save_path = "tcp://127.0.0.1:6379?auth=yourpass&database=0" ; 或使用 phpredis 擴展的 SessionHandler ; 參考文章:PHP 實現 Session 存儲到 Redis
優勢:自動過期、集群共享、高性能、無需清理腳本。