CentOS自建脚本变系统服务,/etc/systemd/system手写unit文件
把脚本塞进系统服务,开机自启、故障重启、日志集中,一条命令全搞定。CentOS早已默认systemd,别再写rc.local,手写unit文件才是正经路。下面把坑填平,照着敲,五分钟完事。

为什么要手写unit文件
rc.local容易丢执行权限,崩溃不会拉,日志分散难查。systemd的unit支持依赖顺序、看门狗、资源限制,一条systemctl enable就能开机自启,比旧模式稳太多。手写unit还能把脚本当正规服务管,运维交接不扯皮。
准备工作:脚本先能裸跑
把脚本放在固定目录,例如/opt/app/start.sh,给执行权限chmod 755,确认用绝对路径能直接跑通。脚本里别用相对路径、别读用户环境变量,所有输出重定向到日志文件,防止journal狂刷。需要环境变量就写死在脚本顶部,或者通过Environment字段注入。
unit文件该放哪
自定义服务一律放/etc/systemd/system/,和系统自带区分,升级不覆盖。文件名即服务名,例如app.service,命令里就systemctl操作app。别放/lib/systemd/system,那边是包管理的地盘,手写的容易被下次更新冲掉。

手写最小可用模板
新建/etc/systemd/system/app.service,内容如下:
[Unit]
Description=My App Startup Script
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/opt/app/start.sh
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
StandardOutput=append:/var/log/app.log
StandardError=append:/var/log/app.log
[Install]
WantedBy=multi-user.target
Type=simple最通用,脚本前台跑不退就行;Restart=on-failure让异常退出自动拉;RestartSec=5s防止死循环打爆CPU。日志直接落文件,journalctl仍能看,排障双保险。
重载与开机自启
保存后执行systemctl daemon-reload,让systemd读新文件。接着systemctl enable app.service写入开机依赖,systemctl start app.service立即跑。status查看状态,绿色active即成功。改完unit必daemon-reload,否则systemd按旧缓存走。
常见排障思路
status里若见exit code 127,八成脚本路径错或缺少解释器;203是权限不足,检查文件系统挂载noexec;挂起timeout可加长TimeoutStartSec。日志优先看/var/log/app.log,再用journalctl -u app.service --since "1 hour ago"过滤,别两眼看屏幕盲猜。
高级玩法:环境变量与预启动
脚本依赖JAVAHOME?在[Service]段加Environment="JAVAHOME=/usr/lib/jvm/java-17",多变量就写多行。需要网络通后再跑,把After=network-online.target和Wants=一起写,防止脚本提前抢跑导致绑定端口失败。依赖数据库就再加After=mariadb.service,启动顺序明明白白。
给脚本加看门狗
脚本里定期touch /run/app.lock,unit里写WatchdogSec=30s,systemd会30秒检查一次文件时间戳,超时没更新就重启服务。自写看门狗比外部cron更及时,还能配Restart=on-watchdog,挂死立即拉新进程。
资源限制防跑飞
在[Service]段追加MemoryMax=500M CPUQuota=50%,可把脚本内存钉死,避免内存泄露拖垮整机。CentOS的cgroup v2已默认启用,systemd直接写就行,无需额外工具。
多实例模板
同脚本要跑多份,只需建app@.service,把ExecStart=/opt/app/start.sh %i,启动时systemctl start app@foo.service,%i会被替换成foo,一份文件N个实例,省得复制粘贴。
升级回滚零 downtime
脚本更新先systemctl stop app,替换文件后systemctl start app,中断两秒。对可用性要求高,就写ExecReload,发SIGHUP让脚本热加载配置,做到外部无感。回滚直接切旧脚本,systemctl restart app,一分钟搞定。
卸载清理
systemctl stop app.service && systemctl disable app.service,再rm /etc/systemd/system/app.service,最后daemon-reload,一条多余文件不留。日志按业务策略自己删,别让磁盘爆。
照着上面敲,CentOS自建脚本就能享受正规服务待遇,开机自启、故障重启、日志集中、资源受限,全交给systemd打理。手写unit文件看似多几行,实则省下半夜救火时间,值。

