智能路由器开发之创建一个procd init脚本示例

news2024/11/15 23:32:22

openwrt

智能路由器开发之创建一个procd init脚本示例

Procd init脚本默认提供了许多好用的功能,例如重启策略和能够从UCI系统中存储和读取配置。

设置

举个例子,假设我们想创建一个作为服务的Shell脚本,并且这个服务可以通过消息和超时时间进行配置,以便提醒我们时不时地离开座位休息一下。我们的服务名称将为"myservice",它依赖于以下脚本。

#!/bin/sh
 
#these if statements will check input and place default values if no input is given
#they will also check if input is a number so you can call 
#this script with just a time and it will still work correctly
 
if [ "$1" = '' ]; then
    name="You"
else
    if echo "$1" | egrep -q '^[0-9]+$'; then
        name="You"
    else
        name="$1"
    fi
fi
 
if [ "$2" = '' ]; then
    every="5"
else
    every="$2"
fi
 
if echo "$1" | egrep -q '^[0-9]+$'; then
    every="$1"
fi
 
#endless loop, will print the message every X seconds as indicated in the $every variable
 
while [ 1 ]; do 
    echo "Hey, $name, it's time to get up"
    sleep $every
done
 
exit 0

将脚本放置在 /var/myscript.sh下,并在OpenWrt上运行测试

$ /bin/sh /var/myscript.sh "Name Surname"

openwrt web

创建一个基本的procd脚本

既然我们有一个可用的脚本,我们可以将其转化为一个服务。在"/etc/init.d/myservice"路径下创建一个文件,并将以下内容添加到文件中。

#!/bin/sh /etc/rc.common
USE_PROCD=1
START=95
STOP=01
start_service() {
    procd_open_instance
    procd_set_param command /bin/sh "/var/myscript.sh"
    procd_close_instance
}

首先,它包含了一个服务所需的常用的"/etc/rc.common"文件,该文件定义了几个函数,用于管理服务的生命周期,它支持旧式的init脚本和procd脚本。为了告诉系统我们要使用新的样式,我们设置了USE_PROCD标志。

START选项基本上告诉系统在OpenWrt启动和关闭期间,服务应该何时启动和停止。

目前这个init脚本并不是很有用,但它展示了我们将进一步开发脚本所需的基本构建模块。

启用服务

告诉OpenWrt我们有一个新的服务将要运行

/etc/init.d/myservice enable

这将在目录"/etc/rc.d/“中为我们安装一个符号链接,名称为"S90myservice”,它指向位于"/etc/init.d/“中的相应服务脚本。OpenWrt将根据”/etc/rc.d/"中S*脚本的顺序启动服务。要查看顺序,您可以简单地运行以下命令:

$ ls -la /etc/rc.d/S*

能够影响服务启动顺序非常有用,如果我们的服务依赖于网络,我们需要确保START顺序的索引至少比网络服务的START顺序大1。

对于可选的STOP参数,同样适用相同的规则,只是这次它定义了服务关闭的顺序。要查看激活的关闭脚本,您可以运行以下命令:

$ ls -la /etc/rc.d/K*

您总是需要在脚本中定义一个STARTSTOP序列(您也可以同时定义两者)。如果您定义了STOP序列,您还需要在初始化脚本中定义一个stop_service()处理程序。该处理程序通常负责清理服务资源或在服务重新启动时需要的数据持久化。测试服务

最后,让我们测试一下我们的服务。打开第二个终端连接到OpenWrt设备,并运行以下命令:

$ logread -f

这将在设备上跟踪系统日志。然后启用(如果尚未启用)并启动服务。

$ /etc/init.d/myservice enable
$ /etc/init.d/myservice start

大约5秒后,我们应该在日志中看到消息重复出现,但实际上并没有…我们仍然需要将stdout和stderr重定向到logd,以便在系统日志中看到console.log的输出,使用procd_set_param stdout 1设置log输出终端。

#!/bin/sh /etc/rc.common
 
USE_PROCD=1
 
START=95
STOP=01
 
start_service() {
    procd_open_instance
    procd_set_param command /bin/sh "/var/myscript.sh"
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_close_instance
}

重启服务后,使用logread -f命令,我们能看到下面的log输出:

$ logread -f
... ommitted ... Hey, You, it's time to get up
... ommitted ... Hey, You, it's time to get up
... ommitted ... Hey, You, it's time to get up
... ommitted ... Hey, You, it's time to get up
... ommitted ... Hey, You, it's time to get up
... ommitted ... Hey, You, it's time to get up
...

像上面那样设置一个简单的procd脚本已经给我们带来了一些优势:

  • 共享的API来管理服务
  • 该服务将在每次启动时自动启动
    openwrt web

服务配置

是时候变得更加个性化了,为此我们将使用OpenWrt的UCI配置界面。创建一个名为/etc/config/myservice的配置文件,内容如下:

config myservice 'hello'
	option name 'Joost'
 	option every '5'

UCI将立即识别这个配置,并且可以像下面这样查看我们服务的配置:

$ uci show myservice
myservice.hello=myservice
myservice.hello.name=Joost
myservice.hello.every='5'

也可以单个选项单独设置

$ uci get myservice.hello.name

也可以修改UCI配置项

$ uci set myservice.hello.name=Knight
$ uci commit

现在,我们将对服务脚本进行一些更改,以便在脚本中读取和使用配置。

加载服务配置项

我们已经可以通过将参数传递给节点脚本来传递配置。我们需要做的唯一事情是加载与配置匹配的服务,将我们需要的选项的值存储到某些变量中,并将它们传递给启动脚本的命令。

#!/bin/sh /etc/rc.common
 
USE_PROCD=1
 
START=95
STOP=01
 
CONFIGURATION=myservice
 
start_service() {
    # Reading config
    config_load "${CONFIGURATION}"
    local name
    local every
 
    config_get name hello name
    config_get every hello every
 
    procd_open_instance
 
    # pass config to script on start
    procd_set_param command /bin/sh "/var/myscript.sh" "$name" "$every"
    procd_set_param file /etc/config/myservice
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_close_instance
}

我们也可以通过下面的命令传递新的配置项

$ uci set myservice.hello.name=Woodrow Wilson Smith
$ uci commit

请注意,在服务脚本中,参数被引号引起来,这样我们就可以在name选项中使用空格。如果我们不这样做,每个名称部分都将被视为单独的参数。

除了加载和传递配置到我们的脚本之外,我们还添加了其他内容。

#//
procd_set_param file /etc/config/myservice
#//

有了这行代码,我们只需要在配置发生更改时重新启动服务。

$ /etc/init.d/myservice reload

openwrt acc

高级选项

还有一些在procd脚本的"instance block"中可以配置的选项,这些选项可能会很有用。我在这里列举了一些,但并不意味着包含了所有内容。

  • respawn
    在某些情况下,当您的服务意外停止时,可以自动重新启动它。
procd_set_param respawn \
      ${respawn_threshold:-3600} \
      ${respawn_timeout:-5} ${respawn_retry:-5}
  • pidfile
    存储pid的文件
procd_set_param pidfile $PIDFILE
  • env vars
    传递环境变量到你的进程
procd_set_param env A_VAR=avalue
  • ulimit

如果您需要为进程设置资源限制,可以使用以下方法:

procd_set_param limits core="unlimited"

要查看在OpenWrt设备上的系统范围内的ulimit设置,您可以运行以下命令:

$ ulimit -a
-f: file size (blocks)             unlimited
-t: cpu time (seconds)             unlimited
-d: data seg size (kb)             unlimited
-s: stack size (kb)                8192
-c: core file size (blocks)        0
-m: resident set size (kb)         unlimited
-l: locked memory (kb)             64
-p: processes                      475
-n: file descriptors               1024
-v: address space (kb)             unlimited
-w: locks                          unlimited
-e: scheduling priority            0
-r: real-time priority             0
  • user

修改运行服务的用户,请使用下面的命令:

procd_set_param user nobody 

默认情况下,OpenWrt只有一个’root’用户或’nobody’作为进程所有者。
您可以按照通常的Linux方式添加用户,请参阅在OpenWrt中创建非特权用户。如果您正在创建一个实际的软件包,您可以使用buildpackage定义,在软件包安装时让OpenWrt生成用户。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/605512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言---初识指针

1、指针是什么 指针是什么? 指针理解的2个要点: ​ 1、指针是内存中一个最小单元的编号,也就是地址。 ​ 2、平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量 总结:指针就是地址&#xff…

Docker+Jenkins+Gitee自动化部署maven项目,加入Nexus镜像仓库(补充篇)

1.前言 Hello,各位小伙伴,大家好!!! 在【DockerJenkinsGitee自动化部署maven项目】一文中,我们介绍了如何使用Jenkins来实现自动化部署maven项目,没读过的小伙伴可以去回顾一下,这…

【求 一个人去给多个人拜年 的最短路径】【枚举所有 拜访顺序】新年好

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录)   文章字体风格: 红色文字表示&#…

ChatGPT 70个插件小测全纪录

以下插件排序按照 ChatGPT all plugins 列表,评分基于国人使用场景。 1)Polarr:用于处理和编辑图片的工具 Polarr插件可以帮助用户进行各种图片编辑任务,包括调整亮度、对比度、饱和度,应用滤镜,裁剪图片,以及其他一些高级的图片处理功能。这个插件可以让ChatGPT更好地…

章节1:XXE漏洞-上

章节1:XXE漏洞-上 01 XML基础知识 XML eXtensible Markup Language 可扩展标记语言 XML用途 配置文件 交换数据 XML内容 XML格式要求 XML文档必须有根元素XML文档必须有关闭标签XML标签对大小写敏感XML元素必须被正确的嵌套XML属性必须加引号 XML格式校验 …

耗时 48小时整理了网络安全学习路线,非常详细!

前言 上次发的文章【都2023年了,还在问网络安全怎么入门】很多小伙伴在评论区回复不知道怎么学习,我也反思了一下,确实没写到学习方法和路线,所以这一期就出一一个怎么学习网络安全的学习路线和方法,觉得有用的话三连…

mvn 打包jar包。 Docker 部署 jar 包程序

默认你已经安装了jdk和maven 并且配置了环境变量. 这里贴出自己的环境配置(mac) # Maven3.6.3 export M2_HOME/Users/cc/maven3.6.3/apache-maven-3.6.3 export M2$M2_HOME/bin export PATH$M2:$PATH# java8 export JAVA_HOME/Library/Java/JavaVirtualMachines/jdk1.8.0_36…

表白墙的实现【前后端交互】

目录 一、Servlet API 详解 1. HttpServletRequest 1.1 HttpServletRequest 方法 1.2 getParameter 2.HttpServletResponse 2.1 HttpServletResponse 方法 2.2 代码示例: 设置状态码 2.3 代码示例: 重定向 二、表白墙 1.准备工作 2.约定前后端交互接口 2.1 接口一…

项目引入Spring Security的参考步骤token

后端&#xff1a; 1、在数据库中创建t_user用户表&#xff0c;参照建表SQL。 2、pom文件中引入Spring Security依赖、JWT依赖&#xff08;复制粘贴即可&#xff09; <!--security--> <dependency> <groupId>org.springfr…

全志V3S嵌入式驱动开发(pwm驱动)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 pwm驱动也是常见的一种驱动方式。常见的pwm&#xff0c;其实就是一组方波&#xff0c;方波中的高低电平之比称之为空占比。通过调节这个空占比&…

前端学习--ES6模块化与异步编程高级用法

一、ES6模块化 1.1 概念与规则 ES6 模块化规范是浏览器端与服务器端通用的模块化开发规范 ES6 模块化规范中定义&#xff1a; 每个 js 文件都是一个独立的模块导入其它模块成员使用 import 关键字向外共享模块成员使用 export 关键字 1.2 在node.js体验es6模块化 配置如下&…

【问题】常见问题解决方法

记录在项目运行中遇到的问题&#xff0c;和常用的软件安装包 文章目录 安装包下载第一章&#xff1a;运行C/C小白运行须知1.DevC运行&#xff08;最简单&#xff0c;推荐&#xff09;2.Visual Studio 运行3.VC运行 第二章&#xff1a;运行C#项目1.VS环境2.打开C#项目启动失败&a…

LiteDram仿真验证(二):仿真中,DDR3初始化问题

目录 前言一、讨论1、[init_done never goes to 1 in simulation #145](https://github.com/enjoy-digital/litedram/issues/145)2、[Add ECP5 support to standalone core generator #106](https://github.com/enjoy-digital/litedram/issues/106)3、[Help generating DDR3 Ve…

【unity插件】2d切割破坏插件-Smart Slicer 2D

文章目录 效果1.切割2.破坏3.创建源码使用1.导入插件2.摄像机3.新建地面4.新建切割刀5.新建切割食物6. 运行即可不同slicer Type的切割刀类型测试1.线性2.Complex3.点4.多边形5.explode6.创建效果 1.切割

华为OD机试之数列描述(Java源码)

数列描述 题目描述 有一个数列a[N] (N60)&#xff0c;从a[0]开始&#xff0c;每一项都是一个数字。数列中a[n1]都是a[n]的描述。其中a[0]1。规则如下&#xff1a; a[0]:1a[1]:11(含义&#xff1a;其前一项a[0]1是1个1&#xff0c;即“11”。表示a[0]从左到右&#xff0c;连续出…

Java简单实现短信验证登录(Session、Redis)

前端设计 <div class"login-form"><div style"display: flex; justify-content: space-between"><el-input style"width: 60%" placeholder"请输入手机号" v-model"form.phone" ></el-input><e…

winform的RichTextBox控件追加文本及图片(实现笔记录入和笔记搜索功能)

在工作中&#xff0c;在工作中&#xff0c;难免有一些笔记要记录下来&#xff0c;方便后续工作中快速找到。之前用的是共享文档来记录的&#xff0c;但有一个缺点就是随着写的内容越来越多&#xff0c;打开变得很慢&#xff0c;搜索更加慢&#xff0c;网络不好的时候&#xff0…

Redis的常用数据结构之有序集合类型

有序集合的特点 集合中的元素有序&#xff0c;不可以重复与列表通过索引实现有序不同&#xff0c;有序集合实现有序的方式是通过给每一个集合元素设置一个分数score字段作为排序依据集合中的元素不能重复&#xff0c;但是score可以重复无法通过某一个下标的方式获取元素单个集…

大数据:spark环境搭建,local模式,standalone模式,zookeeper standby,yarn模式

大数据&#xff1a;spark环境搭建&#xff0c;local模式 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;or…

chatgpt赋能python:Python列表倒序排列

Python列表倒序排列 介绍 Python是一种强大的编程语言&#xff0c;经过多年的发展&#xff0c;它已成为最受欢迎的编程语言之一。Python列表是一个非常有用的数据结构&#xff0c;它允许您将多个项目组合在一起&#xff0c;并可以轻松地对它们进行排序和操作。本篇文章将介绍…