PHP 上传文件的脚本在终端中有效,但不能像使用 incron 自动调用一样
PHP script to upload file works in terminal, but not as automatical call with incron
我有一个 PHP 脚本可以使用 cURL 在 Sharepoint 上上传文档。
如果我 运行 终端中的 scipt,上传过程正常。
因为我想在这个文件被更改时自动调用脚本,所以我使用 incron 来检测相应文件夹中的更改并触发 PHP 脚本的调用。
我的 incron 文件如下所示:
/var/www/[further path]/temp IN_MODIFY,IN_CREATE /usr/bin/php /var/www/[further path]/uploadToSharepoint.php
当我查看系统日志时,我可以看到脚本调用已由 incron 正确触发。但由于某些原因,该文件没有上传到 Sharepoint。
我也尝试创建具有全局写入权限的文件,但这并没有解决我的问题。
-rwxrwxrwx 1 www-data www-data 49058 Mär 3 10:28 [file].xlsx
这是我正在调用的脚本:
包括'database.php';
$username="[username]";
$password="[password]";
$localFileURL="/var/www/[further path]/temp/";
$files = scandir($localFileURL, 1);
$newest_file = $files[0];
$pathToUpload=getTeamPath($newest_file);
uploadDocument($pathToUpload . '/' . $newest_file, $localFileURL . $newest_file,$username, $password);
function uploadDocument($dest, $localFile,$username, $password){
$fp = fopen($localFile, 'r');
// Connecting to website.
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
curl_setopt($ch, CURLOPT_URL, $dest);
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 86400); // 1 Day Timeout
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile));
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
curl_exec ($ch);
if (curl_errno($ch)) {
$msg = curl_error($ch);
}
else {
$msg = 'File uploaded successfully.';
}
curl_close ($ch);
}
非常感谢任何帮助!!!
编辑:
我现在也用普通的 crontab 测试了它,但这也不起作用。它确实执行脚本并循环遍历它而不打印错误,但不上传文件。是否可能与身份验证有关?
如果你说当你 运行
时一切正常
> php /var/www/[further path]/uploadToSharepoint.php
从命令行手动但不是通过 incron 那么最有可能的问题是 user
谁 运行s incrone 命令
选项 1) 尝试识别 运行 执行 incrone 命令的用户,然后切换到该用户并再次 运行 相同 php /var/www/[further path]/uploadToSharepoint.php
选项 2) 尝试 chmod 到 0777 您的扫描目录并使用 incron 再次测试
根据您的问题和评论,这两种方法似乎都不起作用。
根据你的代码,我不太确定你使用的函数
$pathToUpload=getTeamPath($newest_file);
希望它能给你正确的上传路径。
其次,您正在使用 CURLAUTH_NTLM
。我记得有一次我不得不做类似的任务,那次我使用了 CURLAUTH_BASIC
并且它起作用了。所以请尝试一下。
另外 CURLOPT_USERPWD
尝试在其中包含域。作为
curl_setopt($ch, CURLOPT_USERPWD, 'domain\username:password');
此外,您可以尝试设置 CURLOPT_POSTFIELDS
数据将是您的文件的位置获取内容示例:
$data = file_get_contents($file);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
默认情况下,curl 也会尝试发出 get 请求。我感觉应该是POST或者PUT请求。所以请尝试将方法指定为
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
我刚刚阅读了 scandir 函数的文档页面:
http://php.net/manual/en/function.scandir.php
描述第二个参数(sorting_order):
By default, the sorted order is alphabetical in ascending order. If
the optional sorting_order is set to SCANDIR_SORT_DESCENDING, then the
sort order is alphabetical in descending order. If it is set to
SCANDIR_SORT_NONE then the result is unsorted.
当您将 1
指定为 sorting_order 时,它不会根据给定目录中文件的创建或修改时间排序,而是根据文件名排序(降序字母顺序) ).
您的代码中有这两行:
$files = scandir($localFileURL, 1);
$newest_file = $files[0];
第二行的变量命名表明 $files[0]
应该是最新的文件,但通常情况可能并非如此。
当您的临时目录中有多个文件或目录时,这会让人感到困惑,因此可以解释为什么第一次尝试有效而第二次尝试无效。
一个建议是编辑您的 incron 文件并使用 $@
和 $#
作为您的 PHP-脚本的参数,例如:
/var/www/[further path]/temp IN_MODIFY,IN_CREATE /usr/bin/php /var/www/[further path]/uploadToSharepoint.php "$@/$#"
或者出于安全考虑,请使用这种形式:
/var/www/[further path]/temp IN_MODIFY,IN_CREATE /usr/bin/php /var/www/[further path]/uploadToSharepoint.php "$#"
使用第二种形式,仅将刚刚修改或刚刚创建的文件名作为参数提供给您的 PHP-脚本。
然后你可以改变这一行:
$newest_file = $files[0];
为此:
$newest_file = $argv[1];
请注意,要使 $argv
正常工作,您需要启用此选项:
http://php.net/manual/en/ini.core.php#ini.register-argc-argv
最后证明,这是一个代理设置问题。
无论出于何种原因,apache 网络服务器以及 incron/cron 都无法识别机器中设置的环境变量
(http_proxy, https_proxy...)
因此,直接在我的 curl 命令中设置代理和代理端口 解决了我的问题。
curl_setopt($ch, CURLOPT_PROXY, '[ip.ip.ip...]');
curl_setopt($ch, CURLOPT_PROXYPORT, '[port]');
可以在提供的链接中找到有关设置 proxy and proxyport 的更多信息。
感谢大家的积极贡献,很高兴我终于找到了解决问题的方法!
我有一个 PHP 脚本可以使用 cURL 在 Sharepoint 上上传文档。 如果我 运行 终端中的 scipt,上传过程正常。
因为我想在这个文件被更改时自动调用脚本,所以我使用 incron 来检测相应文件夹中的更改并触发 PHP 脚本的调用。
我的 incron 文件如下所示:
/var/www/[further path]/temp IN_MODIFY,IN_CREATE /usr/bin/php /var/www/[further path]/uploadToSharepoint.php
当我查看系统日志时,我可以看到脚本调用已由 incron 正确触发。但由于某些原因,该文件没有上传到 Sharepoint。 我也尝试创建具有全局写入权限的文件,但这并没有解决我的问题。
-rwxrwxrwx 1 www-data www-data 49058 Mär 3 10:28 [file].xlsx
这是我正在调用的脚本:
包括'database.php';
$username="[username]";
$password="[password]";
$localFileURL="/var/www/[further path]/temp/";
$files = scandir($localFileURL, 1);
$newest_file = $files[0];
$pathToUpload=getTeamPath($newest_file);
uploadDocument($pathToUpload . '/' . $newest_file, $localFileURL . $newest_file,$username, $password);
function uploadDocument($dest, $localFile,$username, $password){
$fp = fopen($localFile, 'r');
// Connecting to website.
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
curl_setopt($ch, CURLOPT_URL, $dest);
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 86400); // 1 Day Timeout
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile));
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
curl_exec ($ch);
if (curl_errno($ch)) {
$msg = curl_error($ch);
}
else {
$msg = 'File uploaded successfully.';
}
curl_close ($ch);
}
非常感谢任何帮助!!!
编辑: 我现在也用普通的 crontab 测试了它,但这也不起作用。它确实执行脚本并循环遍历它而不打印错误,但不上传文件。是否可能与身份验证有关?
如果你说当你 运行
时一切正常> php /var/www/[further path]/uploadToSharepoint.php
从命令行手动但不是通过 incron 那么最有可能的问题是 user
谁 运行s incrone 命令
选项 1) 尝试识别 运行 执行 incrone 命令的用户,然后切换到该用户并再次 运行 相同 php /var/www/[further path]/uploadToSharepoint.php
选项 2) 尝试 chmod 到 0777 您的扫描目录并使用 incron 再次测试
根据您的问题和评论,这两种方法似乎都不起作用。
根据你的代码,我不太确定你使用的函数
$pathToUpload=getTeamPath($newest_file);
希望它能给你正确的上传路径。
其次,您正在使用 CURLAUTH_NTLM
。我记得有一次我不得不做类似的任务,那次我使用了 CURLAUTH_BASIC
并且它起作用了。所以请尝试一下。
另外 CURLOPT_USERPWD
尝试在其中包含域。作为
curl_setopt($ch, CURLOPT_USERPWD, 'domain\username:password');
此外,您可以尝试设置 CURLOPT_POSTFIELDS
数据将是您的文件的位置获取内容示例:
$data = file_get_contents($file);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
默认情况下,curl 也会尝试发出 get 请求。我感觉应该是POST或者PUT请求。所以请尝试将方法指定为
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
我刚刚阅读了 scandir 函数的文档页面: http://php.net/manual/en/function.scandir.php
描述第二个参数(sorting_order):
By default, the sorted order is alphabetical in ascending order. If the optional sorting_order is set to SCANDIR_SORT_DESCENDING, then the sort order is alphabetical in descending order. If it is set to SCANDIR_SORT_NONE then the result is unsorted.
当您将 1
指定为 sorting_order 时,它不会根据给定目录中文件的创建或修改时间排序,而是根据文件名排序(降序字母顺序) ).
您的代码中有这两行:
$files = scandir($localFileURL, 1);
$newest_file = $files[0];
第二行的变量命名表明 $files[0]
应该是最新的文件,但通常情况可能并非如此。
当您的临时目录中有多个文件或目录时,这会让人感到困惑,因此可以解释为什么第一次尝试有效而第二次尝试无效。
一个建议是编辑您的 incron 文件并使用 $@
和 $#
作为您的 PHP-脚本的参数,例如:
/var/www/[further path]/temp IN_MODIFY,IN_CREATE /usr/bin/php /var/www/[further path]/uploadToSharepoint.php "$@/$#"
或者出于安全考虑,请使用这种形式:
/var/www/[further path]/temp IN_MODIFY,IN_CREATE /usr/bin/php /var/www/[further path]/uploadToSharepoint.php "$#"
使用第二种形式,仅将刚刚修改或刚刚创建的文件名作为参数提供给您的 PHP-脚本。
然后你可以改变这一行:
$newest_file = $files[0];
为此:
$newest_file = $argv[1];
请注意,要使 $argv
正常工作,您需要启用此选项:
http://php.net/manual/en/ini.core.php#ini.register-argc-argv
最后证明,这是一个代理设置问题。
无论出于何种原因,apache 网络服务器以及 incron/cron 都无法识别机器中设置的环境变量 (http_proxy, https_proxy...)
因此,直接在我的 curl 命令中设置代理和代理端口 解决了我的问题。
curl_setopt($ch, CURLOPT_PROXY, '[ip.ip.ip...]');
curl_setopt($ch, CURLOPT_PROXYPORT, '[port]');
可以在提供的链接中找到有关设置 proxy and proxyport 的更多信息。
感谢大家的积极贡献,很高兴我终于找到了解决问题的方法!