嵌入式的ubuntu系统如何写好SysV Init脚本呢?与system服务又有什么差别呢?一起随着文章来探究吧。
问题背景
许多传统Linux服务仍使用SysV Init脚本(/etc/init.d/),但在Systemd系统中,这些脚本需通过systemd-sysv-generator换为原生服务单元。若脚本未遵循Linux Standard Base (LSB)规范,会导致以下问题:
SysV Init脚本规范指南
1. 必须支持的标准命令脚本需实现以下命令:
1.case"$1" in2.start)3.# 启动服务逻辑4.;;5.stop)6.# 停止服务逻辑7.;;8.restart)9.# 建议直接调用自身stop再start,或委托给Systemd10.$0 stop11.$0 start12.;;13.status)14.# 返回服务运行状态(必需!)15.if pidof -x "$DAEMON" >/dev/null; then16.echo "Service is running"17.exit018.else19.echo "Service is stopped"20.exit3 # LSB规范:未运行状态码21.fi22.;;23.*)24.echo "Usage: $0 {start|stop|restart|status}"25.exit1esac
2. LSB头部注释(必需)在脚本开头添加元数据:
1.### BEGIN INIT INFO2.# Provides: my_service3.# Required-Start: $network $syslog4.# Required-Stop: $network $syslog5.# Default-Start: 23456.# Default-Stop: 0167.# Short-Description: My Custom Service8.# Description: This service does something magical.
3. 正确退出状态码退出码含义
退出码含义0成功1泛型错误2无效命令参数3服务未运行(status命令专用)4权限不足4. 避免破坏Systemd的特性Systemd 是一个进程生命周期管理器,它需要直接跟踪服务的主进程(PID)。如果服务脚本不遵循规范,会导致Systemd无法正确管理服务状态(如判断是否运行、自动重启等)。4.1 禁止后台化进程4.1.1 错误写法
# 传统SysV脚本中常见的后台化方式/usr/bin/my_daemon --config /etc/my.conf &
4.1.2 问题
4.1.3 正确写法
# 使用 exec 替换当前进程(Shell脚本进程被替换为服务进程)exec /usr/bin/my_daemon --config /etc/my.conf
4.1.4 原理
4.2 日志输出规范4.2.1 错误写法
# 直接输出到控制台或文件echo "Starting service..." > /dev/console/usr/bin/my_daemon >> /var/log/my_service.log2>&1
4.2.2 问题
4.2.3 原理
5. 注册服务依赖SysV脚本需通过 LSB头部注释 声明依赖关系,帮助Systemd理解服务启动顺序和条件。这是SysV与Systemd兼容的关键!5.1 LSB头部详解
### BEGIN INIT INFO# Provides: my_service # 服务名称(唯一标识)# Required-Start: $network $syslog # 依赖的服务或系统设施# Required-Stop: $network $syslog # 停止时的依赖# Default-Start: 2345 # 启用服务的运行级别# Default-Stop: 016 # 禁用服务的运行级别# Short-Description: My Service # 简短描述# Description: Long description here.### END INIT INFO
5.1.1 关键字段Required-Start 服务启动前必须就绪的依赖项,例如:
5.2 依赖注册命令5.2.1 目的将LSB头部中的依赖关系转换为系统实际的启动链接(符号链接到 /etc/rcX.d/ 目录)。
Debian/Ubuntu:# 生成依赖链接 sudo update-rc.d my_service defaults
# 移除依赖链接sudo update-rc.d my_service remove
5.3 依赖不注册的后果假设 my_service 依赖网络,但未声明 $network:
6. 总结
创建并启用 SysV Init 脚本的完整流程
1. 创建 SysV Init 脚本的位置SysV Init 脚本必须放置在 /etc/init.d 目录下,这是所有 SysV 风格服务脚本的标准位置。Systemd 的兼容层(systemd-sysv-generator)会自动扫描此目录,将符合规范的脚本转换为 Systemd 服务单元。
2. 创建脚本的步骤
2.1 创建脚本文件使用文本编辑器(如 nano)在/etc/init.d/下创建脚本文件:
sudo nano /etc/init.d/my_service
2.2 编写脚本内容粘贴以下模板(需根据实际服务修改):
#!/bin/bash### BEGIN INIT INFO# Provides: my_service# Required-Start: $network $syslog# Required-Stop: $network $syslog# Default-Start: 2345# Default-Stop: 016# Short-Description: My Custom Service# Description: This service does something important.### END INIT INFO
# 服务主程序路径DAEMON="/usr/bin/my_daemon"NAME="my_service"
case"$1" instart)echo "Starting $NAME"exec $DAEMON;;stop)echo "Stopping $NAME"killall -9 $DAEMON;;restart)$0 stop$0 start;;status)if pidof -x "$DAEMON" >/dev/null; thenecho "$NAME is running"exit0elseecho "$NAME is stopped"exit3fi;;*)echo "Usage: $0 {start|stop|restart|status}"exit1esac
exit0
3. 启用服务的两种方式3.1 传统 SysV 方法(兼容 Systemd)
# Debian/Ubuntusudo update-rc.d my_service defaults
3.2 Systemd 原生方法(推荐)
# 直接通过 Systemd 启用(等效于 update-rc.d)sudo systemctl enable my_serviceSystemd 会自动生成符号链接:Created symlink /etc/systemd/system/multi-user.target.wants/my_service.service → /lib/systemd/system/my_service.service.
4. 验证脚本兼容性4.1 检查 LSB 头部合规性
# Debian/Ubuntusudo insserv -n my_service
输出应无错误,显示依赖关系已解析。4.2 查看 Systemd 生成的单元文件
# 查看生成的 .service 文件systemctl cat my_service输出示例:# /run/systemd/generator.late/my_service.service# Automatically generated by systemd-sysv-generator
[Unit]Documentation=man:systemd-sysv-generator(8)SourcePath=/etc/init.d/my_serviceDescription=My Custom ServiceAfter=network.target syslog.target
[Service]Type=forkingRestart=noTimeoutSec=5minIgnoreSIGPIPE=noKillMode=processGuessMainPID=noRemainAfterExit=yesExecStart=/etc/init.d/my_service startExecStop=/etc/init.d/my_service stopExecReload=/etc/init.d/my_service restart
5. 管理服务
# 启动服务sudo systemctl start my_service
# 查看状态systemctl status my_service
# 停止服务sudo systemctl stop my_service
# 重启服务sudo systemctl restart my_service
6. 关键注意事项6.1 避免冲突配置如果服务已存在 Systemd 原生单元文件(如/lib/systemd/system/my_service.service),需删除或禁用它,否则 SysV 脚本可能被忽略。6.2 禁用传统服务干扰停止并禁用旧版networking服务(如果存在):
systemctl stop networkingsudo systemctl disable networking
6.3 日志输出规范确保服务进程的日志输出到 stdout/stderr,而非直接写入文件。Systemd 会通过 journalctl 捕获日志:
journalctl -u my_service -f
7. 总结步骤命令/操作目的创建脚本sudo nano /etc/init.d/my_service定义服务行为赋予执行权限sudo chmod +x /etc/init.d/my_service确保脚本可执行启用服务sudo systemctl enable my_service设置开机自启验证 Systemd 兼容性systemctl cat my_service检查自动生成的单元文件管理服务生命周期systemctl start/stop/restart my_service控制服务运行状态通过遵循上述步骤,您可以在 Systemd 系统中安全地使用 SysV Init 脚本,同时享受 Systemd 的监控和管理功能。但长期来看,仍建议迁移到原生 Systemd 服务单元(.service 文件),以充分利用资源控制、依赖管理和自动重启等高级特性。
EM系列储能边缘智能网关
EM系列储能边缘智能网关是ZLG致远电子专为新能源储能系统设计的一款高性能、多接口通讯管理设备,可在储能系统应用中作为边缘EMS(能源管理系统)总控、通讯管理机、规约转换器或BAU(电池管理总控)使用。该系列产品集成丰富的外设接口,支持各类BMS、PCS、空调、电表、屏显等设备的通讯传输,且软件上支持RT-Linux、Ubuntu等操作系统,支持IEC-61850/IEC-104/EtherCAT等专用协议,可广泛满足各类储能系统的本地能源管理应用需求。
全部0条评论
快来发表一下你的评论吧 !