Linux 系统的 NAS 之路——systemd 基础及非容器应用的部署
tags: NAS, LinuxLinux 系统的 NAS 之路—— systemd 基础及非容器应用的部署
使用容器部署应用固然方便,但还是存在不少缺点的:
- 占用空间较大,由于每个镜像都额外带了很多依赖,会导致镜像比程序本身大很多。再加上容器镜像“层”的概念,不及时清理冗余镜像的话,时间长了硬盘空间直接爆炸。
- 网络性能问题,尽管 host 网络可以与主机共享网络协议栈,但容器中也许会存在不少的冗余服务(例如有的容器默认 Nginx 会占用 80 端口),这些服务会让主机网络很难管理。而桥接网络的话,会有一些性能损失。
因此对于某些轻量化,易部署的应用,我更推荐用 systemd 进行处理。
系统级 systemd
系统级 systemd 服务默认以 root 用户运行,但可以在配置文件中指定用户。
有些发行版 systemd 配置文件在 /etc/systemd/system/
sukipai@DESKTOP-F3AQEDF:/etc/systemd$ tree -L2
.
├── network
├── system
│ ├── basic.target.wants
....
│ ├── sysinit.target.wants
│ ├── systemd-homed.service.wants
│ ├── systemd-journald.service.wants
│ └── timers.target.wants
└── user
├── basic.target.wants
├── dbus.service -> /usr/lib/systemd/user/dbus-broker.service
├── sockets.target.wants
└── timers.target.wants
但 Fedora 系统的配置在 /usr/lib/systemd/system,.service 文件就是一个服务文件。
如果你的服务程序需要以 root 身份运行,就把 service 文件放在这里。
[Unit]
Description=My Simple Service
After=network.target
[Service]
ExecStart=/usr/bin/python3 /path/to/your/script.py
Restart=always
User=root
[Install]
WantedBy=multi-user.target
服务文件的三个区块
服务配置其实就三个区块。理解了它们,systemd 就学会了七成:
[Unit]— 描述与依赖。After=network.target表示网络就绪后再启动此服务[Service]— 核心配置。ExecStart指定运行命令,Restart定义重启策略,User指定运行用户[Install]—enable时挂载到哪个启动级别。WantedBy=multi-user.target表示进入多用户模式时自动启动
关键字段 Type=
[Service] 里有一个容易被忽略但很重要的字段——Type,它告诉 systemd 如何判断服务是否启动成功。选错了可能导致 systemd 误判,不断重启服务:
simple(默认)— 程序在前台直接运行,systemd 看到进程启动就认为成功forking— 传统守护进程会 fork 到后台、父进程退出,oneshot— 执行一次就结束,适合一次性脚本任务notify— 程序通过sd_notify()主动通知 systemd 自己已就绪
后面的 mihomo 示例用的就是 Type=simple,这也是最推荐的方式——保持程序在前台即可。
用户级 systemd
不推荐把所有的服务都放在系统级目录里面,许多应用普通用户也可以启动,放在系统级目录下面反而会降低安全性。
用户级 systemd 配置目录:~/.config/system/user
服务配置:
[Unit]
Description=My Simple Service
After=network.target
[Service]
ExecStart=/usr/bin/python3 /path/to/your/script.py
Restart=always
[Install]
WantedBy=defualt.target
这项服务会以当前用户启动,即便服务被黑,攻击者能获取到的文件权限是有限的,被限定在当前用户范围内。
使用用户级 systemd 的时候不要加 sudo
重载配置文件:
systemctl --user daemon-reload
启动/停止服务:
systemctl --user start/stop SERVICE
自启动服务:
systemctl --user enable SERVICE
相比系统级 systemd,主要使用方式区别在于不加 sudo 和添加–user 参数。
查看服务日志(journalctl)
服务跑起来后第一件事就是看它正不正常。systemctl status 可以快速了解概况:
systemctl --user status mihomo
输出中重点关注两行:
Loaded: loaded— 配置文件已被加载Active: active (running)— 正在运行;如果显示failed则启动失败
更详细的排查要靠日志。systemd 的日志统一由 journalctl 管理,用它替代直接读文本日志文件:
# 查看某个服务的全部日志
journalctl --user -u mihomo.service
# 实时跟踪日志(类似 tail -f)
journalctl --user -u mihomo.service -f
# 只看最近 20 条
journalctl --user -u mihomo.service -n 20
系统级服务去掉 --user 即可,不加 sudo 只能看到当前用户的日志。
mihomo 部署示例
mihomo 是一款分流软件,支持多种代理协议和规则分流。
安装 mihomo
从 MetaCubeX/mihomo 下载对应架构的二进制文件。
将这个文件放在用户目录下,比如 ~/applications/mihomo/mihomo
添加你的配置文件到 ~/applications/mihomo/mihomo/config.yaml,然后测试运行:
cd ~/applications/mihomo/
./mihomo -d .
确认无误后 Ctrl+C 停止,接下来用 systemd 管理。
用户级 systemd 服务
如果以普通用户运行,使用用户级 systemd,在 ~/.config/systemd/user/ 下创建 mihomo.service:
[Unit]
Description=mihomo proxy service
After=network.target
[Service]
Type=simple
ExecStart=%h/applications/mihomo/mihomo -d %h/applications/mihomo/
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=default.target
%h 会自动展开为当前用户的家目录,这样配置文件路径就不需要硬编码用户名。
然后进行启动与验证:
systemctl --user daemon-reload
systemctl --user enable --now mihomo
systemctl --user status mihomo