我知道有人对此有疑问,但到目前为止没有人帮助我解决我的问题。
我有一个 PHP 脚本,其工作是发送预定的电子邮件。它通过 cURL 调用我控制的 Web 服务来实现此目的。
在浏览器中运行,运行正常。通过 CRON 运行,cURL 响应为空。它永远不会到达网络服务;我知道这一点是因为我让 WS 在联系它时写入了一个文本文件。如果您通过浏览器访问而不是通过 CRON 访问,则会出现这种情况。
我知道 CRON 在不同的环境中运行,并且我不依赖任何环境变量,例如
$_SERVER
。 require()
的路径也不是问题,因为它成功地从该文件中获取数据以连接到数据库。
这个问题建议添加以下 cURL 选项,我已经完成了,但没有骰子:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
这是我的 PHP 脚本:
//prep
define('WS_URL', 'http://mywebservicedomain.com/index.php/web_service');
require '../application/config/database.php';
$db = new mysqli($db['default']['hostname'], $db['default']['username'], $db['default']['password'], $db['default']['database']) or die('failed to connect to DB');
//get scheduled e-mails
$res = $db->query('SELECT * FROM _cron_emails WHERE send_when < NOW()');
//process each...
while ($email_arr = $res->fetch_assoc()) {
//...get API connection info
$api_accnt = $db->query($sql = 'SELECT id, secret FROM _api_accounts WHERE project = "'.$email_arr['project'].'"');
$api_accnt = $api_accnt->fetch_assoc();
//...recreate $_POST env
$tmp = json_decode($email_arr['post_vars'], 1);
$_POST = array();
foreach($tmp as $key => $val) $_POST[$key] = !is_array($val) ? $val : implode(',', $val);
//...call API to send e-mail
$ch = curl_init($url = WS_URL.'/send_scheduled_email/'.$email_arr['email_id'].'/'.$email_arr['store_id'].'/'.$email_arr['item_id']);
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_SAFE_UPLOAD => true,
CURLOPT_SSL_VERIFYHOST => 1, //<-- tried adding this
CURLOPT_SSL_VERIFYPEER => 1, //<-- ditto
CURLOPT_POSTFIELDS => array_merge($_POST, array(
'api_key' => $api_accnt['id'],
'api_secret' => $api_accnt['secret'],
))
));
$resp = curl_exec($ch); //<-- empty when CRON
//if e-mail was sent OK, or decider script said it was ineligible, delete it from the queue
if (($resp == 'ok' || $resp == 'ineligible'))
$db->query('DELETE FROM _cron_emails WHERE id = '.$email_arr['id'].' LIMIT 1');
}
有谁知道为什么只有在 CRON 中运行时才无法通过 cURL 连接到我的 Web 服务?
这是 CRON 作业:
/usr/bin/php /home/desyn/public_html/cron/send_scheduled_emails.php
最终证明这是一个非常特殊且我认为不常见的问题。我怀疑它会对其他人有太大帮助,但我把它留在这里以防万一。
本质上,我的服务器不喜欢通过域进行 cURL 本身。
CRON 脚本中 cURL 调用的服务器与运行 CRON 任务的服务器是同一台服务器(但帐户和网站不同。)
通过浏览器并未证明这是一个问题;仅通过 CRON。
将 cURL 请求更改为使用服务器的本地 IP,而不是使用域,解决了这个问题。
对于遇到同样问题的人,我有另一个解决方案:
不要通过 crontab 调用 php 脚本
/usr/bin/php /home/desyn/public_html/cron/send_scheduled_emails.php
但在 crontab 文件中使用 http 请求:
/usr/bin/curl -s http://example.com/cron/send_scheduled_emails.php > /dev/null
这对我有用。