我必須處理一個遺留項目,其中 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
.這是由於 中的私有 tmp 設定而存在的/lib/systemd/system/apache2.service
。我發現了一點文章在這裡。
每當我呼叫copy(/tmp/....)
PHP 腳本時,它都會在 Apache 特定的私有 tmp 目錄中尋找。/tmp
啟用此選項後,Apache 無法查看 的內容。
因此我只能停用此選項或讓 MySQL 將 CSV 檔案轉儲到其他地方。