# 前言

OpenWrt 默认并不是使用 systemd 来管理服务,而使用 go 的第三方服务包 github.com/kardianos/service 并不能有效的配置好启动项,无法被 OpenWrt 的 Web 管理所接管。因此,我们需要针对 OpenWrt 来客制化编写我们的服务。

参考资料:

  • https://openwrt.org/docs/guide-developer/procd-init-scripts

# 客制化步骤

  1. OpenWrt 构建自己的启动服务

    OpenWrt 后台服务主要分为两个目录,一个是 /etc/init.d/ ,另外一个是 etc/rc.d ,第一个是全部服务(包含未启用的服务),第二个是启用的服务,通常第二个目录中的服务是第一个目录中服务的软链接🔗。

  2. OpenWrt 中的服务定义文件 /etc/rc.common ,这是一个通用的文件,其中包含了一些接口的定义,在本文中主要注意 start_service 这个接口,其基本的接口写法如下:

    h
    start_service() {
             procd_open_instance [instance_name]
             procd_set_param command /sbin/your_service_daemon -b -a --foo # service executable that has to run in **foreground**.
             procd_append_param command -bar 42 # append command parameters
     
             # respawn automatically if something died, be careful if you have an alternative process supervisor
             # if process exits sooner than respawn_threshold, it is considered crashed and after 5 retries the service is stopped
             # if process finishes later than respawn_threshold, it is restarted unconditionally, regardless of error code
             # notice that this is literal respawning of the process, no in a respawn-on-failure sense
             procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
     
             procd_set_param env SOME_VARIABLE=funtimes  # pass environment variables to your process
             procd_set_param limits core="unlimited"  # If you need to set ulimit for your process
             procd_set_param file /var/etc/your_service.conf # /etc/init.d/your_service reload will restart the daemon if these files have changed
             procd_set_param netdev dev # likewise, except if dev's ifindex changes.
             procd_set_param data name=value ... # likewise, except if this data changes.
             procd_set_param stdout 1 # forward stdout of the command to logd
             procd_set_param stderr 1 # same for stderr
             procd_set_param user nobody # run service as user nobody
             procd_set_param pidfile /var/run/somefile.pid # write a pid file on instance start and remove it on stop
             procd_set_param term_timeout 60 # wait before sending SIGKILL
             procd_close_instance
    }

    根据需要修改上述文件,主要修改 proc_set_paramprocd_append_param 这两个参数。

    假设服务程序的二进制文件和配置文件为以下:

    • 二进制文件: /etc/bin/fzu
    • 配置文件: /etc/fzu/config.ini

    则配置文件可以写为:

    #!/bin/sh /etc/rc.common
    START=01
    STOP=90
    USE_PROCD=1
    PROG=/usr/bin/fzu
    start_service(){
    	 procd_open_instance [fzu]
             procd_set_param command /usr/bin/fzu # service executable that has to run in **foreground**.
             procd_append_param command -c /etc/fzu/config.ini # append command parameters
     
             # respawn automatically if something died, be careful if you have an alternative process supervisor
             # if process exits sooner than respawn_threshold, it is considered crashed and after 5 retries the service is stopped
             # if process finishes later than respawn_threshold, it is restarted unconditionally, regardless of error code
             # notice that this is literal respawning of the process, no in a respawn-on-failure sense
             procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
     
             procd_set_param limits core="unlimited"  # If you need to set ulimit for your process
             procd_set_param file /etc/fzu/config.ini # /etc/init.d/your_service reload will restart the daemon if these files have changed
             procd_set_param stdout 1 # forward stdout of the command to logd
             procd_set_param stderr 1 # same for stderr
             procd_set_param user nobody # run service as user nobody
             procd_set_param pidfile /var/run/fzu.pid # write a pid file on instance start and remove it on stop
             procd_set_param term_timeout 60 # wait before sending SIGKILL
             procd_close_instance
    }

    其中第一行是指定使用 #! /bin/sh /etc/rc.common 这个脚本来作为解释器解释上述代码,相关的 fzu 文件都需要修改成「你的启动项名称」。

  3. 当上述服务配置完成后即可用下述命令获取该服务的信息:

    • 启用服务

      /etc/init.d/fzu enable
    • 启动服务

      /etc/init.d/fzu start
    • 停止服务

      /etc/init.d/fzu stop
    • 查看服务的状态

      /etc/init.d/fzu info
      /etc/init.d/fzu status
  4. OpenWrt 的管理页面中也可以看到我们的服务被接管了:

    image-20230827204814960

    点击 启动重启停止 可以轻松执行类似于 3. 中的命令。

更新于 阅读次数