Docker容器中PHP脚本无法重命名CSV文件的问题排查求助
我最近在Docker容器部署的服务器上遇到个棘手的问题:我写了个PHP脚本,用户首次访问网站时会创建一个CSV日志文件(比如test_visit_events_unfinished.csv),用来记录实验相关数据;当用户完成实验后,前端JS会发一个application/x-www-form-urlencoded格式的POST请求到PHP脚本,理论上这时候脚本应该把那个未完成的CSV重命名为test_visit_events_finished.csv,但现在这个重命名操作根本没生效!
我的核心需求
- 新创建的CSV默认命名为
[任务名]_unfinished.csv格式 - 当触发
finish动作时,直接把对应的未完成文件重命名为[任务名]_finished.csv,完全不修改文件内容
我已经尝试过的操作
我反复在代码里加了文件存在性检查,但执行时没有抛出任何错误,反而生成了一个新的_finished.csv文件,原来的_unfinished.csv还好好待在目录里。我已经确认过日志目录的写入权限没问题,现在怀疑是不是文件本身的权限不够?想问问大家怎么才能给这个动态生成的文件自动分配必要的权限?
相关代码片段
PHP核心逻辑
日志目录的定义和三个动作(init/append/finish)的处理代码如下,路径是确认过正确的,init和append动作都能正常工作:
define('LOGDIR', '/var/www/html/logs'); define('LOGEXT', ".csv"); // Check if 'action' key exists in POST data if (isset($_POST['action']) && $_POST['action'] === "init") { // Get name of log file, and ensure it's named with _unfinished by default $fid = $_POST['task'] ?? 'default_task'; // Default task if 'task' is missing $unfinishedFileName = $fid . "_unfinished" . LOGEXT; // Append _unfinished to the filename // Save data for the first time $header = "cursor,timestamp,xpos,ypos,event,xpath,attrs,extras" . PHP_EOL; file_put_contents(LOGDIR . "/" . $unfinishedFileName, $header . $info_data); // Notify recording script echo round(microtime(true) * 1000); } else if (isset($_POST['action']) && $_POST['action'] === "append") { // Get the log file name, use _unfinished if not specified $fid = $_POST['task'] ?? 'default_task'; // Default task if 'task' is missing $unfinishedFileName = $fid . "_unfinished" . LOGEXT; // Append _unfinished to the filename // Don't write blank lines if (trim($info_data)) { file_put_contents(LOGDIR . "/" . $unfinishedFileName, $info_data, FILE_APPEND); } } else if (isset($_POST['action']) && $_POST['action'] === "finish") { // Get the log file name without the suffix $fid = $_POST['taskname'] ?? 'default_task'; // Default task if 'taskname' is missing $unfinishedFileName = $fid . "_unfinished" . LOGEXT; // File with _unfinished suffix $finishedFileName = $fid . "_finished" . LOGEXT; // File with _finished suffix $originalFilePath = LOGDIR . "/" . $unfinishedFileName; $finishedFilePath = LOGDIR . "/" . $finishedFileName; if (file_exists($originalFilePath)) { // Check if the _finished file already exists to avoid overwriting if (!file_exists($finishedFilePath)) { // Rename the file to mark it as finished if (!rename($originalFilePath, $finishedFilePath)) { exit('Failed to mark file as finished'); } echo 'File marked as finished'; } else { exit('A file with _finished already exists'); } } else { exit('Original _unfinished file not found'); } }
目前的问题是:执行finish动作后,目录里确实出现了_finished.csv文件,但原来的_unfinished.csv并没有被重命名(还在原地),感觉像是新建了一个空的完成文件,而不是重命名原文件。
Docker权限配置
我在Dockerfile里设置了目录权限,确保www-data用户能读写日志目录:
RUN usermod -u 1000 www-data && \ groupmod -g 1000 www-data && \ chown -R www-data:www-data /var/www/html && \ chmod -R 755 /var/www/html/logs
前端JS请求代码
触发finish动作的JS函数如下,用来传递要重命名的文件名:
async function finishExperiment(eventFile) { console.log("Now saving to: ", eventFile); // Send a request to the server to mark the log file as "finished" try { const response = await fetch("static/php/writeEvents.php", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" // Set content type to 'x-www-form-urlencoded' }, body: new URLSearchParams({ action: "finish", // The action type to perform taskname: eventFile // The filename to mark as finished }) }); // Handle the response const data = await response.text(); // Assuming the server sends a plain text message } catch (error) { console.error("Error finishing the experiment:", error); } }
有没有大佬能帮我看看问题出在哪?是不是权限的问题?或者是我代码里的某个细节忽略了?
备注:内容来源于stack exchange,提问作者zahntheo

