DAY015 – 上传目录被普通文件占用

举报
yd_287083129 发表于 2026/11/09 16:18:34 2026/11/09
【摘要】 故障场景:首页正常,API health 与订单接口返回 500,日志提示上传目录不可用。server2 状态 INJECTED,2026-07-27 05:00:11 +0800。排障:curl 与日志定位 upload dir unavailable,grep 查配置,ls 发现 uploads 被普通文件占用,file、lsof 确认后 stat 记录、备份、rm 重建目录并 chmod 7

故障场景

故障现象:首页正常,API health 与订单接口返回 500,日志提示上传目录不可用。

服务器状态:

server2:状态 INJECTED;开始时间 2026-07-27 05:00:11 +0800;影响范围 演练项目受影响,SSH 不受影响,非演练业务不应受影响。

排障过程

1、看项目结构文档

- nginx 程序:/usr/sbin/nginx
- systemd 服务:nginx.service
- nginx 配置:/etc/nginx/sites-available/hermes-day015.conf
- nginx 启用配置:/etc/nginx/sites-enabled/hermes-day015.conf
- nginx 日志:/var/log/nginx/hermes-day015-access.log、/var/log/nginx/hermes-day015-error.log
- 应用目录:/opt/hermes-drills/day015/
- API 程序:/opt/hermes-drills/day015/app/api.py
- API 启动脚本:/opt/hermes-drills/day015/start-app.sh
- API 日志:/opt/hermes-drills/day015/logs/api.log
- 可执行场景套件:/home/monika/hermes-ops-drills/standard-scenario-suite.md

## 端口
- nginx:18080
- API:127.0.0.1:18081

2、看本地 curl 返回情况

monika@VM-0-3-ubuntu:~/hermes-ops-drills/DAY015$ curl -i 127.0.0.1:18080/health
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 27 Jul 2026 16:33:37 GMT
Content-Type: application/octet-stream
Content-Length: 9
Connection: keep-alive

nginx ok
monika@VM-0-3-ubuntu:~/hermes-ops-drills/DAY015$ curl -i 127.0.0.1:18080/api/health
HTTP/1.1 500 Internal Server Error
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 27 Jul 2026 16:33:43 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 54
Connection: keep-alive

{"status": "error", "error": "upload dir unavailable"}
monika@VM-0-3-ubuntu:~/hermes-ops-drills/DAY015$ curl -i 127.0.0.1:18080/api/orders
HTTP/1.1 500 Internal Server Error
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 27 Jul 2026 16:33:51 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 54
Connection: keep-alive

{"status": "error", "error": "upload dir unavailable"}

首页与 nginx health 正常,但 API health 与订单接口都返回 500,报错都是 upload dir unavailable,问题出在 API 侧的上传目录上。

3、看后端日志

monika@VM-0-3-ubuntu:~/hermes-ops-drills/DAY015$ tail -n 50 /opt/hermes-drills/day015/logs/api.log
2026-07-27 17:17:35 level=ERROR path=/health error=upload dir unavailable
2026-07-27 17:17:35 127.0.0.1 GET /health 500
2026-07-27 17:17:35 level=ERROR path=/orders error=upload dir unavailable
2026-07-27 17:17:35 127.0.0.1 GET /orders 500

日志显示也是“上传目录不可用”。

4、查上传目录相关配置

monika@VM-0-3-ubuntu:~/hermes-ops-drills/DAY015$ grep -C 5 -n -R "upload" /opt/hermes-drills/day015/
api.py-16: data = {}
api.py-17: for line in CONFIG.read_text().splitlines():
api.py-18: if "=" in line and not line.strip().startswith("#"):
api.py-19: key, value = line.split("=", 1)
api.py-20: data[key.strip()] = value.strip()
api.py-21: upload = (BASE / data.get("UPLOAD_DIR", "../data/uploads")).resolve()
api.py-22: if not upload.exists() or not upload.is_dir():
api.py-23: raise RuntimeError("upload dir unavailable")
api.py-24: probe = upload / ".write-test"
api.py-25: probe.write_text(str(time.time()))
api.py-26: probe.unlink(missing_ok=True)
api.py-27: return data
api.py-29: class Handler(BaseHTTPRequestHandler):
api_config.env-1: APP_NAME=huadong-erp-day015-api
api_config.env-2: UPLOAD_DIR=../data/uploads
api_config.env-3: ORDERS_DB=../data/orders.db
api_config.env-4: SLOW_ORDERS_SECONDS=0

代码逻辑是“当上传目录不存在或者非目录”时返回 upload dir unavailable;环境变量里上传目录是 ../data/uploads。顺着路径线索查看上传目录具体情况。

5、查看上传目录,发现 uploads 变成文件了

monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ ls -lh
total 16K
-rw-rw-r-- 1 monika monika 12K Jul 27 05:00 orders.db
-rw-rw-r-- 1 monika monika 27 Jul 27 05:00 uploads

进来一看,uploads 变成文件了,ls -lh 返回结果最前面不是 d 而是 -。太荒唐了,听 AI 说脚本不够健壮或者写错就会发生这种事情。

在修改为目录前,还需要一些步骤:先查看文件类型,再确认有没有应用正在使用此 uploads 文件。

monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ file uploads
uploads: ASCII text
monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ sudo lsof uploads

lsof 没有返回结果,确认没有正在使用它的进程。

6、记录、备份,再重建目录

确认没有正在使用它的进程后,先记录此文件的修改时间;开了日志审计也应该记录相关这文件的操作,好知道这文件是谁的脚本什么时候生成的;再备份此文件。我没开日志审计,就只用 stat 记录时间信息了。

monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ stat uploads
  File: uploads
  Size: 27         Blocks: 8          IO Block: 4096   regular file
Device: 252,0    Inode: 393473     Links: 1
Access: 2026-07-27 05:00:11.000000000 +0800
Modify: 2026-07-27 05:00:11.000000000 +0800
Change: 2026-07-27 05:00:11.000000000 +0800
 Birth: -
monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ stat uploads > $(date +%F)_uploads_errorfile
monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ ls -lh
total 20K
-rw-rw-r-- 1 monika monika 375 Jul 28 01:04 2026-07-28_uploads_errorfile
-rw-rw-r-- 1 monika monika 12K Jul 27 05:00 orders.db
-rw-rw-r-- 1 monika monika 27 Jul 27 05:00 uploads
monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ cp -a uploads uploads_errorfile.bak
monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ rm uploads
monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ mkdir -p uploads
monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ ls -lh
total 24K
-rw-rw-r-- 1 monika monika 375 Jul 28 01:04 2026-07-28_uploads_errorfile
-rw-rw-r-- 1 monika monika 12K Jul 27 05:00 orders.db
drwxrwxr-x 2 monika monika 4.0K Jul 28 01:12 uploads
-rw-rw-r-- 1 monika monika 27 Jul 27 05:00 uploads_errorfile.bak
monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ sudo chmod 754 uploads

7、最后检查业务恢复状态

monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ curl -i 127.0.0.1:18080/api/orders
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 27 Jul 2026 17:14:22 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 87
Connection: keep-alive

{"orders": [{"id": "SO-001", "status": "paid"}, {"id": "SO-002", "status": "pending"}]}
monika@VM-0-3-ubuntu:/opt/hermes-drills/day015/data$ curl -i 127.0.0.1:18080/api/health
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 27 Jul 2026 17:14:31 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 49
Connection: keep-alive

{"status": "ok", "app": "huadong-erp-day015-api"}

内网公网都正常,业务恢复。

原文首发于个人博客:liujixiang.de5.net

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。