You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP调用Bash脚本清除Cloudflare单URL缓存失败求解决方案

问题:PHP调用Cloudflare缓存清除脚本无输出(手动运行正常)

我遇到了一个问题:我写了Bash脚本用来清除Cloudflare单个URL的缓存,手动通过SSH执行时完全正常,test.log里会显示SUCCESS;但通过PHP的exec()调用这个脚本时,test.log里没有任何输出,说明脚本执行失败了。

我的Bash脚本:

#!/bin/bash
if [ -z "$1" ]; then
    echo "Usage: $0 http://your.domain.com/url"
    exit 0
fi
#get this from Account section in Cloudflare
TOKEN="SECRETTOKEN"
EMAIL="EMAIL"
DOMAIN="DOMAIN"
curl -s https://www.cloudflare.com/api_json.html \
    -d "a=zone_file_purge" \
    -d "tkn=$TOKEN" \
    -d "email=$EMAIL" \
    -d "z=$DOMAIN" \
    -d "url=$1" >> test.log #output to check if this script work

PHP脚本:

<?php
$domain = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
$actual_link = $_SERVER[HTTP_REFERER];
exec("/bin/bash /path/to/bkl.sh $actual_link");
echo "Success";
header('Refresh: 5; URL=' . $_SERVER['HTTP_REFERER']);
?>

实现逻辑是:网站上有个按钮,用户点击后触发PHP脚本,调用Bash脚本清除对应文章URL的Cloudflare缓存,然后重定向回文章页。


排查与解决方案

我从几个常见的问题点入手,帮你逐步解决这个问题:

1. 权限问题(最常见)

PHP运行的用户(通常是www-data、apache或nginx)和你SSH登录的用户不是同一个,很可能没有执行脚本或写入日志的权限:

  • 给Bash脚本添加执行权限:
    chmod +x /path/to/bkl.sh
    
  • 确保test.log所在目录对PHP运行用户有写入权限,比如:
    # 假设PHP用户是www-data
    chown www-data:www-data /path/to/test.log
    chown www-data:www-data /path/to/ # 如果日志在脚本目录,给目录加权限
    

2. 参数传递的特殊字符问题

$_SERVER['HTTP_REFERER']里可能包含&、空格或其他特殊字符,直接传递给Bash会被错误拆分,导致参数无效。解决方法是用escapeshellarg()转义参数:
修改PHP脚本:

<?php
$domain = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
$actual_link = $_SERVER['HTTP_REFERER'];
// 转义URL中的特殊字符
$escaped_link = escapeshellarg($actual_link);
exec("/bin/bash /path/to/bkl.sh $escaped_link");
echo "Success";
header('Refresh: 5; URL=' . $_SERVER['HTTP_REFERER']);
?>

3. 路径问题(绝对路径才可靠)

PHP的exec()运行时的工作目录不一定是脚本所在目录,相对路径的test.log和curl可能找不到:

  • 在Bash脚本里把curl换成绝对路径(可以用which curl获取,比如/usr/bin/curl)
  • 把test.log改成绝对路径,比如/var/log/cloudflare_purge.log,避免相对路径找不到:
    修改Bash脚本的最后一行:
/usr/bin/curl -s https://www.cloudflare.com/api_json.html \
    -d "a=zone_file_purge" \
    -d "tkn=$TOKEN" \
    -d "email=$EMAIL" \
    -d "z=$DOMAIN" \
    -d "url=$1" >> /var/log/cloudflare_purge.log 2>&1

这里的2>&1是把错误输出也写入日志,方便你查看执行失败的具体原因。

4. 捕获PHP执行的调试信息

修改PHP脚本,获取exec()的输出和返回状态,直接在页面上看到执行结果,方便调试:

<?php
$domain = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
$actual_link = $_SERVER['HTTP_REFERER'];
$escaped_link = escapeshellarg($actual_link);
$output = [];
$return_code = 0;
exec("/bin/bash /path/to/bkl.sh $escaped_link", $output, $return_code);

echo "执行返回码:$return_code<br>";
echo "脚本输出:<pre>" . print_r($output, true) . "</pre>";
header('Refresh: 10; URL=' . $_SERVER['HTTP_REFERER']);
?>

返回码为0表示成功,非0就是失败,输出里会有具体的错误提示。

5. 升级到Cloudflare API v4(推荐)

你现在用的是Cloudflare旧版API v1,官方已经推荐使用API v4,稳定性和安全性更好。可以把Bash脚本改成v4版本:

#!/bin/bash
if [ -z "$1" ]; then
    echo "Usage: $0 http://your.domain.com/url"
    exit 0
fi
# 从Cloudflare控制台获取API Token(注意是API Token,不是Global API Key)
TOKEN="YOUR_API_TOKEN"
# 从域名的Overview页面获取Zone ID
ZONE_ID="YOUR_ZONE_ID"

/usr/bin/curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"files": ["'"$1"'"]}' >> /var/log/cloudflare_purge.log 2>&1

这个版本不需要邮箱,用Bearer令牌验证,更安全。


内容的提问来源于stack exchange,提问作者DRMTV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:49:22