我是 cron 工作的新手,不确定这是否可行。
出于安全目的,我考虑制作一个单页脚本来查找某些 GET 值(用户名、密码和安全代码),以确保只有计算机和知道所有 3 个值的人才能运行该命令。
我制作了脚本,它可以在浏览器中运行它,但是是否可以使用 GET 值运行 cron 作业?
一个例子是我跑步
* 3 * * * /path_to_script/cronjob.php?username=test&password=test&code=1234
这可能吗?
$_GET[]
和 $_POST[]
关联数组仅在通过 Web 服务器调用脚本时初始化。 当通过命令行调用时,参数在 $argv
数组中传递,就像 C 一样。
包含传递给脚本的所有参数的数组,当 从命令行运行。
您的命令将是:
* 3 * * * /path_to_script/cronjob.php username=test password=test code=1234
然后,您将使用 parse_str() 来设置和访问参数:
<?php
var_dump($argv);
/*
array(4) {
[0]=>
string(27) "/path_to_script/cronjob.php"
[1]=>
string(13) "username=test"
[2]=>
string(13) "password=test"
[3]=>
string(9) "code=1234"
}
*/
parse_str($argv[3], $params);
echo $params['code']; // 1234
不是对您的问题的直接回答,但我认为是更好的解决方案:
如果你希望除了 cron 之外没有人运行脚本,只需将其放在 web-root 之外。这样就根本无法通过Web服务器进行访问。
如果您确实还需要以特殊用户身份运行该命令,请不要使用 GET
而是让用户登录并检查登录会话(某个设置会话变量...),并仅在该页面中包含脚本。
可公开访问的脚本如下所示:
session_start();
if (isset($_SESSION['user']))
{
include '/path/to/script/outside/of/web-root';
}
else
{
die('No access.');
}
我意识到这篇文章已经有好几年了,但这篇文章对我的帮助最大,所以让我也分享我的发现来帮助其他人。
我正在使用 DirectAdmin,我的 cron 示例两者都有效。我从"将所有 Cron 输出发送到电子邮件"中删除了我的电子邮件地址,因此我不会收到有关我的 cronjobs 的电子邮件通知。
我从一个每 20 分钟运行一次的 cURL 请求开始:
*/20 * * * * /usr/local/bin/curl --silent 'https://demo.tld/app/stats/?update&key=1234'
请注意 URL 周围的 ' ',否则您无法添加多个参数!
我使用该页面作为受 API 启发的方式来触发我从另一个网站收集的一些统计数据的更新,其他人可以从我的网站上以 JSON 形式获取这些统计数据。参数"update"触发更新过程,参数"key"将在验证后触发我只想在 cronjob 请求更新时完成的其他更新操作。
由于上面的 cronjob 基本上在两个方向上都消耗带宽,我想使用基于 PHP 的 cronjob,但遇到了参数问题......所以就在那时,我找到了这篇文章,它节省了我的一天:)
*/20 * * * * /usr/local/bin/php /home/path/to/public_html/app/stats/index.php update key=1234
如您所见,文件名(index.php)现在包含在路径中,然后是参数(没有 ? 和 &'s)。
通过这种方式,您可以让 cronjob 工作,但您只完成了一半,因为参数不会通过 $_GET
传递......当您使用检查$_GET
键对脚本进行编码时,这有点烦人!
那么,它是如何工作的呢?很简单(至少经过一些研究),cronjob 通过一个名为 $argv
的变量将参数传递给脚本。
因此,有了这些知识,我搜索了一种将$argv
转换为$_GET
的方法:
- 我可以手动或通过 cronjob 触发更新。
- 我不必重写整个剧本。
我找到了以下解决方案,我们只想在实际设置$argv
时执行,所以我将其包装在if isset
检查中:
if( isset( $argv ) )
{
foreach( $argv as $arg ) {
$e = explode( '=', $arg );
if( count($e) == 2 )
$_GET[$e[0]] = $e[1];
else
$_GET[$e[0]] = 0;
}
}
希望这对你也有帮助:)
* 3 * * * /path_to_script/cronjob.php?username=test&password=test&code=1234
这行不通
* 3 * * * /path_to_script/cronjob.php username=test password=test code=1234
这行得通
另外,您需要使用 parse_str() 函数并获取值
$str = "first=value&arr[]=foo+bar&arr[]=baz";
parse_str($str);
echo $first; // value
echo $arr[0]; // foo bar
echo $arr[1]; // baz
这将起作用:
* 3 * * * /path_to_script/cronjob.php username=test password=test code=1234
你应该研究get_opt()或$argv函数。
username=test&password=test&code=1234
将成为:
php -r "$_GET["username"]="test"; $_GET["password"]="test"; $_GET["code"]="1234"; include "wp-cron.php";'
当我需要来自 cron 或控制台命令的参数时,我发现使用 getopt()
函数很有用。
此函数将返回选项/参数对数组,或在失败时返回 FALSE。
以下示例直接取自 PHP 文档。
$options = getopt("f:hp:");
var_dump($options);
shell> php example.php -fvalue -h
上面的示例将输出:
array(2) {
["f"]=>
string(5) "value"
["h"]=>
bool(false)
}
有关更多选项和不同的参数,请查看完整的文档。
资源
- getopt() - PHP 文档
如果你的脚本在多个地方被调用(不仅仅是在你的cronjob中),并且你不想改变原始代码(即继续使用$_GET['foo'], $_GET['bar']
或$_POST['foo'], $_POST['bar']
),你可以使用wget(假设它存在/安装在你的服务器上)。
例如:
* 3 * * * wget -qO- 'http://yoursite.com/path_to_script/cronjob.php?username=test&password=test&code=1234' > /dev/null 2>&1
其中-q
是用于安静模式(无输出)的选项,O-
表示Output to stdout
。
由于响应不是您通常保留的内容(保存到文件),因此/dev/null 2>&1
位可确保脚本返回的任何响应(echo
、printf
等)都不会保存在任何地方。