FreeBSD自定义服务
将程序放到后台运行,只解决了当前会话中的执行问题。服务器重启后是否自动启动、程序退出后如何处理,以及管理员怎样检查和停止服务,还需要统一的管理方式。FreeBSD可以通过rc.d脚本管理自定义程序,并使用service执行常见操作。
以下示例以FreeBSD 15.1为环境,创建一个每分钟输出一条状态消息的测试程序,不监听网络端口,也不修改现有网站服务。完成后,再将示例程序替换为自己的应用。
一、确认环境并备份配置
查看系统版本。
freebsd-version
后续操作需要root权限,并在sh环境中执行。
su -
/bin/sh
备份现有配置。
cp -p /etc/rc.conf \
/root/rc.conf.before-siteworker.$(date +%Y%m%d-%H%M%S)
本例使用以下名称和路径。
服务名称 siteworker
运行账号 siteworker
程序路径 /usr/local/libexec/siteworker.sh
服务脚本 /usr/local/etc/rc.d/siteworker
PID文件 /var/run/siteworker.pid
如果服务器已经使用这些名称,应换一组名称并同步调整后续配置,避免覆盖已有程序。
二、创建独立运行账号
先检查账号是否存在。
pw usershow siteworker
如果确认不存在,再创建专用账号。
pw useradd siteworker \
-d /nonexistent \
-s /usr/sbin/nologin \
-w no \
-c "Site worker service account"
该账号不用于交互登录。示例程序不需要root权限,因此由专用账号执行,服务脚本和程序文件仍由root管理。
检查创建结果。
id siteworker
不要为了让程序能够启动,直接给运行账号开放不必要的目录写入权限。
三、创建测试程序
创建目录。
mkdir -p /usr/local/libexec
写入示例程序。
cat > /usr/local/libexec/siteworker.sh <<'EOF'
#!/bin/sh
sleep_pid=
stop_worker()
{
trap '' TERM INT
if [ -n "$sleep_pid" ]; then
kill "$sleep_pid" 2>/dev/null || :
wait "$sleep_pid" 2>/dev/null || :
fi
exit 0
}
trap stop_worker TERM INT
while :; do
printf '%s siteworker heartbeat\n' \
"$(/bin/date -u '+%Y-%m-%dT%H:%M:%SZ')"
/bin/sleep 60 &
sleep_pid=$!
wait "$sleep_pid"
sleep_pid=
done
EOF
设置所有者和执行权限。
chown root:wheel /usr/local/libexec/siteworker.sh
chmod 755 /usr/local/libexec/siteworker.sh
这个程序每分钟输出一条消息。收到停止信号时,会结束等待中的sleep进程,再退出自身。
先检查Shell语法。
/bin/sh -n /usr/local/libexec/siteworker.sh
没有输出且退出状态为0,说明这一步没有发现语法错误;它还不能代替实际运行验证。
四、编写rc.d服务脚本
创建服务脚本目录。
mkdir -p /usr/local/etc/rc.d
写入配置。
cat > /usr/local/etc/rc.d/siteworker <<'EOF'
#!/bin/sh
# PROVIDE: siteworker
# REQUIRE: LOGIN
# KEYWORD: shutdown
. /etc/rc.subr
name="siteworker"
rcvar="siteworker_enable"
load_rc_config "$name"
: "${siteworker_enable:=NO}"
: "${siteworker_run_user:=siteworker}"
pidfile="/var/run/${name}.pid"
command="/usr/sbin/daemon"
procname="/usr/sbin/daemon"
required_files="/usr/local/libexec/siteworker.sh"
siteworker_flags="-c -f -P ${pidfile} -R 5 -u ${siteworker_run_user} -S -T ${name}"
command_args="/usr/local/libexec/siteworker.sh"
run_rc_command "$1"
EOF
设置权限并检查语法。
chown root:wheel /usr/local/etc/rc.d/siteworker
chmod 755 /usr/local/etc/rc.d/siteworker
/bin/sh -n /usr/local/etc/rc.d/siteworker
脚本开头的PROVIDE、REQUIRE和KEYWORD是启动排序及关机处理使用的声明,应保留。
其中,rc.subr提供通用的服务管理逻辑,load_rc_config加载服务配置,run_rc_command根据传入参数执行启动、停止或状态检查。
本例通过daemon管理实际程序,主要参数包括以下几项。
-P记录监管进程的PID。-R 5在被监管程序退出后,等待5秒再启动。-u指定业务程序使用的运行账号。-S将程序输出交给syslog。-T设置日志标识为siteworker。-c将工作目录切换到根目录。
启用自动重新启动时,服务管理应指向监管进程,而不是只记录业务子进程。 如果停止的只是子进程,监管进程可能马上将它重新启动。
五、在不启用开机启动的情况下测试
先临时启动服务。
service siteworker onestart
查看状态。
service siteworker onestatus
one前缀允许本次操作跳过开机启用状态检查,方便先验证脚本,再决定是否长期运行。
检查相关进程。
ps -ax -o user,pid,ppid,command | grep '[s]iteworker'
应能看到监管进程及业务程序。业务程序应使用siteworker账号运行。
确认syslog服务状态。
service syslogd status
在采用常见系统日志规则的环境中,可以检查消息日志。
grep 'siteworker' /var/log/messages | tail -n 10
正常情况下应出现带有siteworker heartbeat的记录。如果服务器调整过syslog规则,需要到实际配置的日志目标中查看。
服务状态显示运行,不等于业务功能一定正常。 本例还需要确认状态消息持续产生;换成真实应用后,应增加对应的业务健康检查。
六、启用开机启动并验证常用操作
测试通过后,先停止临时运行的服务。
service siteworker onestop
写入开机配置。
sysrc siteworker_enable=YES
sysrc siteworker_run_user=siteworker
再正常启动。
service siteworker start
service siteworker status
后续可以使用以下命令管理。
service siteworker restart
service siteworker stop
service siteworker start
每次修改服务脚本或程序后,都应先检查语法,再根据变更内容重启服务,并检查日志。
不必为了验证开机设置立即重启生产服务器。可以先确认配置值,等维护窗口再做完整的重启验证。
sysrc siteworker_enable
七、替换为自己的应用
接入实际程序时,主要调整command_args,使其指向业务程序的真实启动命令。
同时确认以下事项。
- 使用绝对路径,避免依赖交互终端中的
PATH。 - 程序应以前台模式运行,由
daemon负责后台化和监管。 - 运行账号必须能够读取配置及程序文件。
- 需要写入的数据目录应单独授权,不要让服务账号修改启动脚本。
- 工作目录、环境变量及外部依赖需要明确配置。
如果应用已有软件包提供的rc.d脚本,优先使用现成脚本,避免为同一个程序建立两套管理方式。
需要进一步限制应用资源占用时,可以结合站内的FreeBSD资源限制教程设置相应策略。
八、停用服务与常见问题
1. 如何取消开机启动
先停止服务,再关闭开机启用项。
service siteworker stop
sysrc siteworker_enable=NO
这不会删除程序、账号或配置,后续仍可检查和恢复。
2. 为什么结束子进程后,它又出现了
本例使用了daemon -R 5。子进程退出后会被重新启动。需要停止整个服务时,应使用service siteworker stop,不要只结束业务进程。
3. 为什么服务一直处于运行状态,却没有正常工作
程序可能持续启动失败,而监管进程仍在重试。应查看日志,检查运行账号、文件权限和启动参数。自动重新启动不能代替错误修复。
4. 配置了启动依赖,是否代表外部服务已经可用
启动排序只能安排执行顺序,不能保证数据库或远程接口已经能够正常响应。真实应用仍应具备连接重试或明确的启动前检查。
广告合作
QQ群号:4114653
- 本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。邮箱:2942802716#qq.com(#改为@)。
- 本站原创内容未经允许不得转载,转载请注明出处“站长百科”和原文地址。