【Linux】实战:从零编写一个systemd服务实现开机自启
1. 为什么需要systemd服务每次重启服务器后都要手动启动一堆服务作为一名运维老兵我见过太多人用nohup、screen这些土办法跑守护进程结果服务器一重启服务全挂了。其实Linux早就给我们准备好了更专业的解决方案——systemd服务管理。想象一下这样的场景你花了三天三夜写了个数据备份脚本结果某天机房断电重启后发现上周的数据库全量备份都没执行。这时候要是当初配置了systemd服务就不会出现这种人间惨剧。systemd不仅能实现开机自启还能自动重启崩溃的服务、记录日志、限制资源占用堪称服务管理的瑞士军刀。2. 准备你的可执行程序2.1 脚本编写规范先给大家看看我最近写的一个真实案例——网站日志清理脚本#!/bin/bash # 日志目录 LOG_DIR/var/log/nginx # 保留最近7天的日志 DAYS_TO_KEEP7 function cleanup() { echo $(date) - 开始清理日志... /var/log/log_cleaner.log find $LOG_DIR -type f -name *.log -mtime $DAYS_TO_KEEP -delete echo $(date) - 日志清理完成 /var/log/log_cleaner.log } # 主循环 while true; do cleanup # 每天凌晨3点执行 sleep 86400 done这个脚本有几个关键点使用完整路径而非相对路径所有操作都有日志记录用函数封装核心逻辑包含必要的注释2.2 测试脚本可靠性写完脚本别急着配置服务先手动测试几轮# 给执行权限 chmod x /opt/scripts/log_cleaner.sh # 第一次试运行 /opt/scripts/log_cleaner.sh # 查看执行日志 tail -f /var/log/log_cleaner.log # 模拟异常退出 kill -9 $(pgrep -f log_cleaner.sh)我建议至少测试以下场景正常启动/停止手动kill进程修改系统时间测试定时逻辑磁盘空间不足的情况3. 创建systemd服务单元文件3.1 服务文件存放位置系统级服务建议放在/etc/systemd/system/比如我们的日志清理服务sudo vim /etc/systemd/system/log-cleaner.service3.2 完整服务配置示例这是我优化过的生产级配置[Unit] DescriptionNGINX日志清理服务 Afternginx.service Requiresnginx.service StartLimitIntervalSec500 StartLimitBurst5 [Service] Typesimple Userroot Grouproot ExecStart/opt/scripts/log_cleaner.sh Restarton-failure RestartSec30s StandardOutputsyslog StandardErrorsyslog SyslogIdentifierlog_cleaner EnvironmentLOG_LEVELverbose [Install] WantedBymulti-user.target3.3 关键参数详解[Unit] 部分After表示在nginx服务启动后再启动Requires强依赖关系nginx挂了本服务也会停止StartLimit*防止服务崩溃时无限重启[Service] 部分Restarton-failure只有异常退出时才重启RestartSec重启间隔避免频繁重启SyslogIdentifier方便在日志中过滤[Install] 部分WantedBy多用户模式启动适合大多数服务器场景4. 服务生命周期管理4.1 注册并启动服务# 重载systemd配置 sudo systemctl daemon-reload # 设置开机自启 sudo systemctl enable log-cleaner # 立即启动服务 sudo systemctl start log-cleaner # 查看状态 sudo systemctl status log-cleaner4.2 日常维护命令# 查看完整日志 journalctl -u log-cleaner -f # 平滑重启服务 sudo systemctl restart log-cleaner # 临时停止 sudo systemctl stop log-cleaner # 禁用开机启动 sudo systemctl disable log-cleaner4.3 服务故障排查当服务启动失败时我常用的排查步骤检查服务状态systemctl status log-cleaner -l查看详细日志journalctl -xe -u log-cleaner --no-pager手动执行命令sudo -u root /opt/scripts/log_cleaner.sh检查依赖服务systemctl list-dependencies log-cleaner5. 高级配置技巧5.1 资源限制防止服务占用过多资源[Service] ... MemoryLimit512M CPUQuota80% IOWeight1005.2 环境变量管理推荐使用单独的环境文件# /etc/sysconfig/log-cleaner LOG_DIR/var/log/nginx DAYS_TO_KEEP7然后在服务文件中引用EnvironmentFile/etc/sysconfig/log-cleaner ExecStart/opt/scripts/log_cleaner.sh ${LOG_DIR} ${DAYS_TO_KEEP}5.3 多命令服务需要执行多个命令时ExecStartPre/bin/mkdir -p /var/run/myservice ExecStart/usr/bin/myservice --daemonize ExecStop/usr/bin/myservice --shutdown ExecReload/bin/kill -HUP $MAINPID6. 真实案例Python应用服务化以Flask应用为例用gunicorn启动[Unit] DescriptionFlask电商平台API服务 Afternetwork.target redis.service mysql.service [Service] Userappuser Groupappuser WorkingDirectory/opt/apps/ecommerce EnvironmentPATH/opt/apps/venv/bin ExecStart/opt/apps/venv/bin/gunicorn -w 4 -b 0.0.0.0:8000 app:app Restartalways [Install] WantedBymulti-user.target关键点指定虚拟环境路径设置工作目录使用非root用户运行配置正确的进程数(-w参数)7. 常见问题解决方案7.1 服务启动超时如果服务启动较慢需要调整超时时间[Service] ... TimeoutStartSec3007.2 日志文件切割对于长期运行的服务建议配置日志轮转# /etc/logrotate.d/log-cleaner /var/log/log_cleaner.log { daily rotate 30 missingok notifempty compress delaycompress sharedscripts postrotate systemctl kill -s HUP log-cleaner.service endscript }7.3 权限问题处理遇到权限问题时可以检查脚本是否有执行权限服务User/Group配置是否正确文件目录所属用户和权限SELinux上下文配置8. 服务监控与告警8.1 健康检查配置[Service] ... ExecStartPost/bin/bash -c echo $MAINPID /var/run/log-cleaner.pid ExecStopPost/bin/rm -f /var/run/log-cleaner.pid8.2 集成Prometheus监控对于支持metrics的服务EnvironmentPROMETHEUS_MULTIPROC_DIR/tmp/metrics ExecStartPre/bin/mkdir -p /tmp/metrics8.3 邮件告警设置通过systemd的OnFailure触发告警[Unit] OnFailurestatus-email%n.service [Service] ... FailureActionexit配套的邮件服务模板# /etc/systemd/system/status-email.service [Unit] DescriptionSend email notification for %i failure [Service] Typeoneshot ExecStart/usr/local/bin/send-failure-alert.sh %i