【问题标题】:curl php download script works fine in browser but fails in cronjobscurl php下载脚本在浏览器中工作正常,但在cronjobs中失败
【发布时间】:2012-03-30 18:52:06
【问题描述】:

我编写 curl php 脚本,该脚本的工作是在成功登录后从一个网站下载 csv 文件。当我在浏览器中启动它时它工作正常,但当我将它放在 cron 作业列表中时它会失败。我曾经在日志中看到内存耗尽错误,所以我想我的服务器给我的 cron 内存更少。

我该如何解决这个问题?

你可以看到部分代码,它正在做下载工作,这很正常:

<?php
...
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt ($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $postfields);
$fp = fopen("data.csv", "w");
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_exec ($ch);
curl_close ($ch);
fclose($fp);

只想再说一遍,这是代码的一部分,在浏览器中一切正常,在 cron 作业中失败。

【问题讨论】:

  • crontab 条目是什么(假设它是 Linux 操作系统)?
  • 0 */1 * * * cd /home7/philbike/public_html/atlanticauto/assets/components/cronmanager/ && php cron.php ,但这是执行 sn-p 的 modx 扩展。
  • 只是一个想法 - 有不同的 php.ini。从命令行执行是不同的(例如 cronjobs)。

标签: php curl download cron modx


【解决方案1】:

假设您使用标准配置的 CRON,您的 cwd(当前工作目录)是 ~// 或类似的东西,但是当您从网络运行脚本时,您的 cwd设置为dir( __FILE__)(当前脚本目录)。

假设你正在使用脚本/var/www/web1/scripts/script1.php,比:

  • 网络 cwd = /var/www/web1/scripts/
  • CRONs cwd = /var/www

当您使用相对文件名,例如data.csv(开头没有/)时,完整路径创建为CWD . $filename,因此:

  • 网络完整路径/var/www/web1/scripts/data.csv
  • CRON 完整路径 /var/www/data.csv

您可以通过以下方式轻松避免这种情况:

define( 'PATH_ROOT', dirname( __FILE__) . '/');
// ...
curl_setopt ($ch, CURLOPT_COOKIEJAR, PATH_ROOT . 'cookie.txt');
curl_setopt ($ch, CURLOPT_COOKIEFILE, PATH_ROOT . 'cookie.txt');
// ...
$fp = fopen( PATH_ROOT . "data.csv", "w");

还要确保您的系统用户已连接并且脚本将完全运行(检查 CRON 长或给自己发送电子邮件)。

【讨论】:

  • 如果我将在文件开头使用“/”,例如“/data.csv”,如果文件位于 public_html 目录中,它应该可以正常工作吗?
  • @electroid 它将使用文件系统根目录,您必须使用/var/www/public_html/data.csv 或(假设您的脚本在/var/www/public_html/scripts/sub/cron.phpdir( __FILE__) . '/../../data.csv'
  • 无论如何我已经尝试使用 $_SERVER['DOCUMENT_ROOT'] 来执行它。我会尝试以这种方式进行。
【解决方案2】:

通常这意味着你的 PHP (php.ini) 配置在调用你的服务器和通过命令行调用时是不一样的。我不确定这是最佳实践,但我通常让我的 cronjob 在我的脚本上调用 wget,以确保它们在我测试它们的相同环境中运行,即通过网络服务器。

# m h  dom mon dow   command
  * *  *   *   *   wget -O - http://myapp.example.com/cron/run > /dev/null 2>&1

* 表示该命令将在任意位置运行:

  • 分钟
  • 小时
  • 一个月中的哪一天
  • 星期几

-O 选项告诉 wget 不要将脚本的输出写入文件 "> /dev/null 2>&1" 只是重定向脚本的输出以避免 cron 的默认行为(即向用户发送带有命令输出的电子邮件)。

【讨论】:

  • 在我的情况下看起来如何?我的意思是我执行 0 */1 * * * cd /home7/philbike/public_html/atlanticauto/assets/components/cronmanager/ && php cron.php ,只需添加 wget -O ?
  • 不,当然不是... wget 等待一个 URL,您只需将输入的 url 放入浏览器进行测试。 (我编辑我的答案来解释它)。
  • 好的,我想我明白了。但是出于安全原因,我不能像那样使用我的脚本。我的意思是,如果我在 modx 框架中以管理员身份登录,则脚本会在浏览器中启动,但除了其他人之外,它无法执行。
  • 我通常会在我的脚本中添加一个密钥(如果密钥不在获取参数中,我会锁定执行)您还可以检查请求是否来自本地主机或本地 IP 地址,如 127.0 .0.1.
  • 嗨,我试试你的方法。它给了我发送的输出 HTTP 请求,等待响应... 200 OK 长度:未指定 [text/html] 保存到:STDOUT' 0K 298K=0s 2012-03-18 06:00:04 (298 KB/s) - -' 已保存 [4] 看起来不太好,我想保存到 data.csv 文件和这个一个保存在 STDOUT 中。 %)
【解决方案3】:

作为一种解决方法,您可以在浏览器中执行此操作,而无需修改 PHP 脚本。例如:

30 * * * * /usr/bin/lynx -source http://mypage/status/cron &gt; /dev/null

它的行为就像在浏览器中一样,并且可以避免你不得不处理代码和环境问题。

或者,您可以使用 wget 代替 PHP 脚本。

【讨论】:

    【解决方案4】:

    “php /home7/philbike/public_html/atlanticauto/assets/components/cronmanager/cron.php”命令怎么样?它在你的终端上工作吗?

    【讨论】:

    • 是的,它工作正常。我可以在 modx 框架中看到日志消息,它显示了我的 sn-ps 执行了什么。
    【解决方案5】:

    终于让我的第一个设置一切正常:cd /home7/philbike/public_html/atlanticauto/assets/components/cronmanager/ &amp;&amp; php cron.php

    我应该在不使用系统变量的情况下直接写入 csv 文件的路径:

    /home7/philbike/public_html/atlanticauto/data.csv
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      • 1970-01-01
      • 2014-09-02
      • 2021-04-22
      • 2014-06-27
      • 2017-05-07
      • 1970-01-01
      相关资源
      最近更新 更多