我必须处理一个遗留项目,其中 PHP API 从 MySQL 创建 CSV 导出并提供文件以供稍后下载。
问题是 API 无法将 CSV 文件复制到可从中下载的目录(通过 Apache)
这个过程如下:
- 有人点击网站上的按钮来创建 csv 导出。
- 该 API 创建一个 SQL 语句并使用 shell_exec(mysql ...) 执行它;
- 数据库使用数据创建一个 CSV 文件并将其放入 /tmp/
- API 将文件复制到 apache 专用的下载目录中
- API 向点击按钮的用户发送一封包含下载链接的邮件。
除步骤 4 外,上述所有操作均有效。
我在 API 中发现:
$exportCommand = "mysql ....";
// mysqlExportTmpDir = /tmp
// mysqlExportTargetDirectory = download directory for apache
$moveExportFileCommand = "cp ".$this->mysqlExportTmpDir."/$filename ".$this->mysqlExportTargetDirectory;
shell_exec("( $exportCommand; $moveExportFileCommand; $sendNotificationCommand) &");
正如我所说,MySQL 命令有效,邮件通知有效,但 cp 命令无效。
当我查看日志时,看到此错误:
cp:无法统计“/tmp/610278f414d84.csv”:没有这样的文件或目录
我还尝试shell_exec("ls /tmp/*.csv");
检查旧的导出文件是否对 API 可见,但是我得到了以下信息:
ls:无法访问‘/tmp/*.csv’:没有此文件或目录
其中肯定有 CSV 文件。因此我认为这可能是权限问题,并尝试在终端中执行此操作:sudo -u www-data cp /tmp/610274ad5a8a5.csv /path/to/api/download
。我从日志中复制了 cp 命令,因此它应该完全相同。
可以了。现在我很困惑,因为 www-data 运行 Apache,并且使用 shell_exec("whoami") 我还从 PHP API 获取 www-data。也许该sudo -u www-data cp ...
命令没有按我预期的方式工作(我期望拥有与该用户相同的权限)。但我不知道。
有人知道为什么 PHP 无法访问 /tmp 中的 csv 文件并将它们复制到不同的目录吗?
目标目录属于组 www-data,其中的文件可以从浏览器下载。
我知道从数据库导出数据的方法很奇怪,但直到一年前它似乎还有效。现在我公司里已经没有人参与这个项目了,我不知道发生了什么变化。
答案1
Apache 有一个私有的 tmp 目录,位于/tmp/*apache2.service*/tmp
。这是因为 中的 private tmp 设置而存在的/lib/systemd/system/apache2.service
。我发现了一些文章在这里。
每当我调用PHP 脚本时,它都会在 Apache 特定的私有 tmp 目录中查找。启用此选项后,copy(/tmp/....)
Apache 无法查看内容。/tmp
因此我只能禁用此选项或让 MySQL 将 CSV 文件转储到其他地方。