Мне приходится иметь дело с устаревшим проектом, в котором PHP API создает экспорт CSV из MySQL и предоставляет файл для последующей загрузки.
Проблема в том, что 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: невозможно stat '/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") я также получаю www-data из PHP API. Возможно, команда sudo -u www-data cp ...
не работает так, как я ожидал (я ожидал, что у меня будут те же права, что и у этого пользователя). Но я не знаю.
Кто-нибудь знает, почему PHP не может получить доступ к файлам csv в /tmp и скопировать их в другой каталог?
Целевой каталог принадлежит группе www-data, и файлы в нем можно загрузить из браузера.
Я знаю, что подход к экспорту данных из базы данных странный, но он, казалось, работал до прошлого года. Сейчас в моей компании больше нет никого из этого проекта, и я не знаю, что изменилось.
решение1
Существует частный каталог tmp для Apache, расположенный в /tmp/*apache2.service*/tmp
. Он существует из-за частной настройки tmp в /lib/systemd/system/apache2.service
. Я нашел немногостатья здесь.
Всякий раз, когда я вызываю copy(/tmp/....)
PHP-скрипт, он будет искать в специфическом для Apache частном каталоге tmp. Apache не может видеть содержимое /tmp
при включенной этой опции.
Поэтому я могу только отключить эту опцию или заставить MySQL сохранять CSV-файлы в другом месте.