在云服务器上部署 Web 服务前,先把文件存放位置、账户权限边界和后台进程托管方式理顺,能减少后续运维中的权限报错与服务异常。
本文围绕日常运维常用的四个基础模块展开:FHS 目录划分、用户与八进制权限位、进程信号控制,以及 systemd 服务单元与 journalctl 日志检索。
FHS 文件系统目录划分
Linux 遵循 FHS(Filesystem Hierarchy Standard,文件系统层次结构标准)。按标准目录存放配置、站点产物与日志,后续备份与迁移时只需打包对应目录:
| 目录路径 | 职责说明 | Web 服务器常见用途 | 注意事项 |
|---|---|---|---|
/etc |
系统与服务的静态配置文件 | /etc/ssh/sshd_config(SSH 配置)、/etc/nginx/conf.d/(Nginx 站点配置)、/etc/systemd/system/(自定义服务单元) |
不在此目录存放大体量网站资源或持续增长的日志文件 |
/var/www 或 /srv |
对外提供服务的站点数据与发布产物 | /var/www/blog/releases/(存放按时间戳归档的静态 HTML 产物)与 /var/www/blog/current(指向当前生效版本的软链接) |
确保父目录链条对 Web 容器或 www-data 用户具备 x(可进入)权限 |
/var/log |
系统与守护进程的滚动日志 | /var/log/nginx/access.log、/var/log/auth.log(SSH 登录审计)、/var/log/journal/(systemd 日志) |
配合 logrotate 或 journald.conf 限制最大体积,避免日志占满根分区 |
/opt 或 /usr/local |
第三方软件包与自定义运维脚本 | /usr/local/bin/deploy-blog.sh(发布与回滚脚本)、/opt/containers/(Docker Compose 编排目录) |
自写脚本可放在 /usr/local/bin/ 并设为 755,在系统 $PATH 中可直接调用 |
/home/<user> |
普通运维用户的家目录 | /home/ops/.ssh/authorized_keys(SSH 登录公钥)、日常临时工作区 |
避免把生产 Web 根目录直接建在 /home/<user> 下,防止家目录权限收紧后 Web 进程无权读取 |
/proc 与 /sys |
内核虚拟文件系统(内存映射,不占磁盘) | /proc/meminfo(内存状态)、/proc/cpuinfo、/proc/<pid>/fd(查看进程打开的文件句柄) |
不对 /proc 执行 chmod;内核参数统一通过 /etc/sysctl.d/ 管理 |
初始化站点目录结构
拿到一台新服务器后,可先建立站点发布目录、编排目录与备份目录:
1 | # 创建站点多版本发布目录、Docker 编排目录与备份目录 |
用户身份与 POSIX 权限模型
Linux 是多用户操作系统。进程(如 Nginx Worker 或容器内进程)读取文件时,内核会按 Owner(属主 u)→ Group(属组 g)→ Others(其他用户 o)的顺序核对三组权限位:r(读取 = 4)、w(写入 = 2)、x(执行或进入目录 = 1)。
1. 文件与目录在 rwx 语义上的区别
rwx 对普通文件和对目录(Directory)的作用不同:
- 对于普通文件(如
index.html、id_ed25519):r (4):读取文件内容(如cat index.html)。w (2):修改文件内容,但不决定能否删除该文件(删除文件取决于父目录的w权限)。x (1):将文件作为程序或脚本执行(如./deploy.sh)。静态网页文件(.html、.css、.png)不需要x权限,常规权限设为644(rw-r--r--)。
- 对于目录(如
/var/www/blog):r (4):列出目录内的文件名列表(ls)。w (2):在目录内新建、删除、重命名文件(需同时具备x权限)。x (1):进入(cd)或穿过该目录访问其子文件。如果/var/www的权限是750且属组不匹配,即使里面的index.html设为644,Nginx 进程也会因为无法穿过父目录而返回403 Forbidden。
2. 服务器常用权限配置命令
1 | # 1. 静态网站目录与文件标准权限(目录 755 可进入,文件 644 只读) |
进程生命周期、文件描述符与信号机制(Signals)
维护 Web 服务时,经常需要“修改配置后平滑生效”或“切分日志时不中断当前连接”,这依赖于 POSIX 进程信号(Signals)。
1. 常用运维信号说明
| 信号名称 | 信号编号 | 默认行为与作用 | 常见使用场景 |
|---|---|---|---|
SIGHUP |
1 |
终端挂断;守护进程通常用于重载配置(Reload) | nginx -s reload 或 systemctl reload ssh:Master 进程重读配置并启动新 Worker,旧 Worker 处理完当前连接后退出 |
SIGINT |
2 |
键盘中断信号(等同于终端按下 Ctrl + C) |
终止前台正在运行的调试进程或构建命令 |
SIGUSR1 |
10 |
用户自定义信号 1;Nginx 用作重新打开日志文件 | logrotate 将旧 access.log 重命名后,向 Nginx 发送 USR1,使其向新创建的空日志文件写入,释放旧文件句柄 |
SIGTERM |
15 |
正常终止信号(kill <pid> 或 docker stop 默认发送) |
通知进程保存状态、关闭监听套接字、完成当前请求后退出 |
SIGKILL |
9 |
内核强制终止信号(不可捕获、不可忽略) | 仅在进程无响应且 SIGTERM 等待超时后使用;直接 kill -9 可能导致锁文件残留或未刷盘数据丢失 |
2. 删除大日志文件后磁盘空间未释放的原因
当某个日志文件(例如 /var/log/nginx/access.log)增长到几十 GB 时,如果直接执行 rm -f /var/log/nginx/access.log,运行 df -h 往往会发现磁盘占用并没有下降。
原因:在 Linux 文件系统中,文件由目录项(dentry / 文件名指针)和索引节点(inode / 磁盘数据块)组成。rm 只移除了目录项链接;只要 Nginx 进程仍持有该文件的文件描述符(File Descriptor),内核就不会回收对应 inode 占用的磁盘块。
1 | # 1. 对比磁盘块占用(df)与目录实际文件汇总(du)的差值 |
systemd 服务管理与 journalctl 日志检索
Ubuntu、Debian、Rocky Linux 等主流发行版均采用 systemd 作为 PID 1 初始化系统。把自建脚本或后台服务写成标准的 .service 单元,可以统一管理开机自启、异常重启与日志收集。
1. systemd 服务单元配置示例
假设需要在服务器上常驻运行一个站点同步或后台任务进程,可在 /etc/systemd/system/blog-worker.service 中编写如下配置:
1 | [Unit] |
启用并检查该服务的常用命令:
1 | # 重新加载 systemd 配置并设置开机自启 |
2. 使用 journalctl 过滤系统与服务日志
journalctl 支持按服务单元、时间范围和日志级别检索:
1 | # 1. 查看指定服务在最近 1 小时内的日志 |
日常运维基础核对表
| 检查项 | 核验命令 | 核对结果 |
|---|---|---|
| 站点目录权限链 | namei -l /var/www/blog |
从 /、/var、/var/www 到 /var/www/blog 每一级均具备 r-x 权限 |
| 磁盘与句柄状态 | df -h && df -i && sudo lsof +L1 |
磁盘容量与 inode 使用率均低于 80%,无未释放的 deleted 大文件句柄 |
| 服务自启状态 | systemctl list-unit-files --state=enabled |
核心服务(ssh、docker、ufw)均处于 enabled 状态 |
| 日志磁盘占用 | journalctl --disk-usage |
系统日志总占用控制在 500MB 以内 |