嵌入式Linux设置开机自动运行程序(基于BusyBox init)

2023-11-05

目的

开机自动运行程序,或者说系统启动时自动运行程序,这是经常会需要用到的功能。这个功能通常依托于 init 程序实现。 init 是Linux在内核启动完成之后第一个启动的程序,该程序会运行一些特定位置的脚本,相当于实现开机运行程序的效果。

在常见的Linux发行版中 init 程序主要为 SysVinitSystemd 。在嵌入式Linux中根文件系统通常使用 buildroot 来建立, buildroot 默认是基于 BusyBox 构建根文件系统的,这种方式下默认的 init 程序可以称其为 BusyBox init 。 这篇文章将介绍通过 BusyBox init 实现开机自动运行程序的功能。

BusyBox init启动流程

inittab

BusyBox init 会在启动后读取 /etc/ 目录下的 inittab 文件,下面是其内容样式:

# /etc/inittab
#
# Copyright (C) 2001 Erik Andersen <andersen@codepoet.org>
#
# Note: BusyBox init doesn't support runlevels.  The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use
# sysvinit.
#
# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id        == tty to run on, or empty for /dev/console
# runlevels == ignored
# action    == one of sysinit, respawn, askfirst, wait, and once
# process   == program to run

# Startup the system
::sysinit:/bin/mount -t proc proc /proc
::sysinit:/bin/mount -o remount,rw /
::sysinit:/bin/mkdir -p /dev/pts /dev/shm
::sysinit:/bin/mount -a
::sysinit:/bin/mkdir -p /run/lock/subsys
::sysinit:/sbin/swapon -a
null::sysinit:/bin/ln -sf /proc/self/fd /dev/fd
null::sysinit:/bin/ln -sf /proc/self/fd/0 /dev/stdin
null::sysinit:/bin/ln -sf /proc/self/fd/1 /dev/stdout
null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr
::sysinit:/bin/hostname -F /etc/hostname
# now run any rc scripts
::sysinit:/etc/init.d/rcS

# Put a getty on the serial port
console::respawn:/sbin/getty -L  console 0 vt100 # GENERIC_SERIAL

# Stuff to do for the 3-finger salute
#::ctrlaltdel:/sbin/reboot

# Stuff to do before rebooting
::shutdown:/etc/init.d/rcK
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r

可以从注释中看到这个文件记录的是一条条按照一定规则编写的语句。

BusyBox init 会在启动后执行第三个字段为 sysinit 的语句中的命令,会在关机时执行第三个字段为 shutdown 的语句中的命令。

在这里添加语句就可以实现开机运行程序了,不过一般不推荐这么做。

rcS 和 rcK

从上面文件中可以看到 sysinit 系列的语句最后一条会去执行 /etc/init.d/ 目录下的 rcS 脚本,也即开机时其它工作完成后会执行 rcS 这个脚本。同样的会在关机时先执行 /etc/init.d/ 目录下的 rcK 脚本。这两个脚本内容如下:

rcS

#!/bin/sh


# Start all init scripts in /etc/init.d
# executing them in numerical order.
#
for i in /etc/init.d/S??* ;do

     # Ignore dangling symlinks (if any).
     [ ! -f "$i" ] && continue

     case "$i" in
        *.sh)
            # Source shell script for speed.
            (
                trap - INT QUIT TSTP
                set start
                . $i
            )
            ;;
        *)
            # No sh extension, so fork subprocess.
            $i start
            ;;
    esac
done

rcK

#!/bin/sh


# Stop all init scripts in /etc/init.d
# executing them in reversed numerical order.
#
for i in $(ls -r /etc/init.d/S??*) ;do

     # Ignore dangling symlinks (if any).
     [ ! -f "$i" ] && continue

     case "$i" in
        *.sh)
            # Source shell script for speed.
            (
                trap - INT QUIT TSTP
                set stop
                . $i
            )
            ;;
        *)
            # No sh extension, so fork subprocess.
            $i stop
            ;;
    esac
done

可以看到 rcS 脚本会依据文件名排序依次读取 /etc/init.d/ 目录下名字为 S??* 格式的脚本文件,并执行其中的 start 方法。同用的 rcK 脚本会依据文件名逆排序读取 /etc/init.d/ 目录下名字为 S??* 格式的脚本文件,并执行其中的 stop 方法。

设置开机自动运行程序

对于我们需要设置开机运行程序而言,可以编写名字为 S??* 格式的脚本文件存放到 /etc/init.d/ 目录下,这样它就会在开机时被调用执行其中的 start 方法了。

名字为 S??* 格式的脚本文件默认在 /etc/init.d/ 目录下已经有一些了:
在这里插入图片描述

我们可以参考它们来编写自己的脚本开机脚本,这里创建名为 S77test 的文件,其中内容如下:

#!/bin/sh

umask 077

start() {
        echo "Starting test log: Naisu is coming!!!"
}

stop() {
        echo "Stopping test log: Naisu is leaving!!!"
}

restart() {
        stop
        start
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart|reload)
        restart
        ;;
  *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
esac

exit $?

备注1:各个函数中不建议出现长时间阻塞的操作,如果有需求建议在命令后面加上 (空格)& 放到后台运行;
备注2:行尾必须是以只有换行符形式,不能是windows上回车加换行的形式;

调整脚本权限:

chmod 755 /etc/init.d/S77test

下面就是脚本在开关机时运行的演示了:
在这里插入图片描述

总结

在使用 BusyBox init 的嵌入式Linux系统中设置开机自动运行程序并不复杂,只要了解其脚本调用流程基本就可以了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式Linux设置开机自动运行程序(基于BusyBox init) 的相关文章

  • 如何使用 sed 仅删除双空行?

    我找到了这个问题和答案 https stackoverflow com questions 4651591 howto use sed to remove only triple empty lines关于如何删除三重空行 但是 我只需要对
  • 如何更改 Ubuntu 14.04 上的 php-cli 版本?

    我是 Linux 新手 在篡改时破坏了一些 php 设置 如果我执行一个包含以下内容的 php 脚本 phpinfo 它显示 php 版本为 5 6 但通过命令行 如果我运行php v它返回 7 0 版本 我想让两个版本匹配 我怎样才能修复
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte
  • 在Linux上编译C# + WPF以便在Windows上运行

    我有一个 C 应用程序 其中某些部分是使用 WPF 编写的 Mono 不支持 可以在 Linux 上编译这个应用程序吗 最终 该应用程序将在 Windows 上运行 但它是更大框架的一部分 并且我们的整个构建过程在 Linux 上运行 因此
  • xsel -o 对于 OS X 等效项

    是否有一个等效的解决方案可以在 OS X 中抓取选定的文本 就像适用于 Linux 的 xsel o 一样 只需要当前的选择 这样我就可以在 shell 脚本中使用文本 干杯 埃里克 你也许可以安装xsel在 MacOS 上 更新 根据 A
  • 在 Linux 上更快地分叉大型进程?

    在现代 Linux 上达到与 Linux 相同效果的最快 最好的方法是什么 fork execve combo 从一个大的过程 我的问题是进程分叉大约 500MByte 大 并且一个简单的基准测试只能从进程中实现约 50 个分叉 秒 比较最
  • awk 子串单个字符

    这是columns txt aaa bbb 3 ccc ddd 2 eee fff 1 3 3 g 3 hhh i jjj 3 kkk ll 3 mm nn oo 3 我可以找到第二列以 b 开头的行 awk if substr 2 1 1
  • 强制卸载 NFS 安装目录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • 通过特定分隔符删除字符串

    我的文件中有几列 其中第二列有 分隔符 我想删除第二列中的第一个 第三个和第四个字符串 并将第二个字符串留在该列中 但我有正常的分隔符空间 所以我不知道 input 22 16050075 A G 16050075 A G 22 16050
  • 使用 grep 查找包含所有搜索字符串的行

    我有一个文件 其中包含很多与此类似的行 id 2796 some model Profile message type MODEL SAVE fields account 14 address null modification times
  • 从 csv 文件中删除特定列,保持输出上的相同结构[重复]

    这个问题在这里已经有答案了 我想删除第 3 列并在输出文件中保留相同的结构 输入文件 12 10 10 10 10 1 12 23 1 45 6 7 11 2 33 45 1 2 1 2 34 5 6 I tried awk F 3 fil
  • 如何根据 HTTP 请求使用 Python 和 Flask 执行 shell 命令并流输出?

    下列的这个帖子 https stackoverflow com questions 15092961 how to continuously display python output in a webpage 我能够tail f网页的日志
  • 域套接字“sendto”遇到“errno 111,连接被拒绝”

    我正在使用域套接字从另一个进程获取值 就像 A 从 B 获取值一样 它可以运行几个月 但最近 A 向 B 发送消息时偶尔会失败 出现 errno 111 连接被拒绝 我检查了B域套接字绑定文件 它是存在的 我也在另一台机器上做了一些测试 效
  • 加载数据infile,Windows和Linux的区别

    我有一个需要导入到 MySQL 表的文件 这是我的命令 LOAD DATA LOCAL INFILE C test csv INTO TABLE logs fields terminated by LINES terminated BY n
  • nslookup 报告“无法解析 '(null)': 名称无法解析”,尽管它成功解析了 DNS 名称

    我在 ubuntu 上 并且正在运行 docker 默认桥接网络 我有 Zookeeper kafka 的容器化版本 以及我编写的与 kafka 对话的应用程序 I do a docker exec it
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • arm64和armhf有什么区别?

    Raspberry Pi Type 3 具有 64 位 CPU 但其架构不是arm64 but armhf 有什么区别arm64 and armhf armhf代表 arm hard float 是给定的名称Debian 端口 https
  • 尝试安装 LESS 时出现“请尝试以 root/管理员身份再次运行此命令”错误

    我正在尝试在我的计算机上安装 LESS 并且已经安装了节点 但是 当我输入 node install g less 时 出现以下错误 并且不知道该怎么办 FPaulMAC bin paul npm install g less npm ER
  • init 中的 Swift 通用约束

    我有通用的 我希望能够用特定的约束来初始化它 约束仅用于初始化 班里的其他人并不关心 这是一个简化的示例 struct Generic
  • 两种情况或 if 哪个更快? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我必须制作一个 非常 轻的脚本 它将接受用户的选项并调用脚本中的函数来执行一些任务 现在我可以使用 IF 和 CASE 选项 但我想知道两

随机推荐

  • 后端进阶之路——深入理解Spring Security配置(二)

    前言 作者主页 雪碧有白泡泡 个人网站 雪碧的个人网站 推荐专栏 java一站式服务 前端炫酷代码分享 uniapp 从构建到提升 从0到英雄 vue成神之路 解决算法 一个专栏就够了 架构咱们从0说 数据流通的精妙之道 后端进阶之路 文章
  • A/B测试是什么?面试官把我问懵了!

    什么是A B测试 A B测试是为 web 或 app 界面或流程制作两个 A B 或多个版本 在同一时间维度 分别让组成成分相同 相似 的访客群组 目标人群 随机的访问这些版本 收集各群组的用户体验数据和业务数据 最后分析 评估出最好版本
  • Golang 枚举详解

    什么是枚举 枚举 Enumeration 是一种常见的编程概念 它定义了一组命名常量 我们知道在 Go 语言中定义常量是这样的形式 const A a B b 开发者可以使用枚举创建复杂的 有限的常量集 这些常量集具有有意义的名称和唯一的值
  • 将 Bean 注入 Spring 容器的方法

    这里写目录标题 1 Configuration Bean 2 Componet ComponentScan 3 Import 注解导入 3 1 Import 直接导入类 3 2 Import ImportSelector接口 3 3 Imp
  • Microsoft Visual Studio 2013产品激活密钥

    win7 win8 win10系统下Visual Studio 2013各个版本的密钥 Visual Studio Ultimate 2013 KEY BWG7X J98B3 W34RT 33B3R JVYW9 Visual Studio
  • unity3D 物体跟随移动

    脚本挂载移动的物体上 public class Player MonoBehaviour public float Speed 4 Use this for initialization void Start Update is calle
  • c++打怪小游戏——修仙之路1.5

    这次我们要出示的程序是修仙之路1 5版本的 这个程序在c 打怪小游戏 修仙之路1 0多加了好几个功能 这次我们在这个程序中多加了一些代码 我们为下面的优化多准备一个头文件 include
  • MAVEN在IDEA中的应用

    idea集成maven插件 settings gt 输入maven gt 选择本地maven安装路径 配置文件以及本地仓库的路径 创建非web的maven工程 创建工程 gt 选择maven 下一步之后填写项目的坐标 类似于全类名 下一步之
  • Zotero win10/mac/iPad三台设备同步

    刚入坑Zotero 发现同步功能很强大 刚好手上有三台设备 就试着捣鼓了下 最终结果不错 记录一下 参考来源 https sspai com post 64283 少数派 用 Zotero 坚果云搞定多设备文献管理 https blog c
  • 虚拟机中linux_server搭建

    linux server environment 1 Installation in vmware workstation 1 1 steps 略 普通的虚拟机系统安装模式 2 linux 中存储设备的使用 linux 中所有存储设备都是通
  • 华为云服务器无法ssh连接&&可以公网ip访问

    基本是SSH服务没有打开的原因 在华为的配置里面默认打开了22号端口 但是需要修改ssh配置文件 首先从华为云服务管理界面远程登录进去 然后会看到 然后登陆之后修改ssh的配置文件 sudo vi etc ssh sshd config 将
  • Scrapy 爬虫完整案例—从小白到大神(银行网点信息为例)

    采用selenium界面抓取信息 需要渲染界面 并且也是单线程操作 效率极低 一晚上只爬去了一个工行的数据 突然想到了分布式爬虫 安装 Scrapy pip版本过于老旧不能使用 需要升级pip版本 输入python m pip instal
  • OpenCV学习三十三:pointPolygonTest 检测点是否在轮廓内

    opencv函数 pointPolygonTest C double pointPolygonTest InputArray contour Point2f pt bool measureDist 用于测试一个点是否在多边形中 当measu
  • 云计算知识点

    一 理解云计算 一 云计算的基本概念 1 定义 云计算是以服务的形式 按需向用户提供计算资源的一种模式 它是分布式计算的一种特殊形式 引入了效用模型来远程供给可扩展和可测量的资源 2 基本要点 提供IT资源 包括计算 存储以及网络资源 提供
  • 用MATLAB实现雅克比迭代、高斯-赛德尔迭代以及超松弛迭代

    文章目录 前言 一 解线性方程组的方法 二 解线性方程组的迭代法及其代码实现 1 迭代法的收敛性 2 基本参数设置 3 雅克比 Jacobi 迭代 4 高斯 塞德尔 Gauss Seidel 迭代 5 超松弛 SOR 迭代 总结 前言 近期
  • 在opencv3中的机器学习算法

    在opencv3 0中 提供了一个ml cpp的文件 这里面全是机器学习的算法 共提供了这么几种 1 正态贝叶斯 normal Bayessian classifier 我已在另外一篇博文中介绍过 在opencv3中实现机器学习之 利用正态
  • 线性回归实现人脸识别——ORL数据集

    今天写一个比较简单的机器学习例子 使用线性回归实现人脸识别 使用的数据集是ORL数据集 算法描述 输入 图片矩阵img 标签信息label 测试图片test 对每一个类 第一步 从图片矩阵中读出来一类图片 划分为训练集 X 与测试集 y 第
  • 求 1-10 的奇数之积,偶数之和。

    i 1 even sum 0 偶数 odd sum 0 奇数 while i lt 10 循环10次 if i 2 0 even sum even sum i else odd sum odd sum i i 1 print 1 10偶数之
  • React-从0到1搭建一个React项目(一)

    文章目录 架构介绍 第三方组件库 项目准备 环境准备 使用create react app初始化项目 创建项目目录结构 安装第三方库 利用工作之余的时间学习了react 今年一回来 部门要在公众号上面开发一个积分商城 于是准备让我用reac
  • 嵌入式Linux设置开机自动运行程序(基于BusyBox init)

    文章目录 目的 BusyBox init启动流程 inittab rcS 和 rcK 设置开机自动运行程序 总结 目的 开机自动运行程序 或者说系统启动时自动运行程序 这是经常会需要用到的功能 这个功能通常依托于 init 程序实现 ini