Post-在 Yocto-built 上安装脚本 linux
Post-install script on Yocto-built linux
我需要 运行 Yocto 构建的目标 OS 上的脚本。
此脚本需要 运行 作为安装的一部分,因此只能 运行 一次(在整个 OS 安装之后或第一次启动时)。它不能在主机系统上 运行,因为它取决于仅存在于目标上的硬件 IO。
另一个次要的限制是 rootfs 被挂载为只读,但我想这可以通过让脚本重新挂载为 rw 并在执行后再次重新挂载为 r 或类似的东西来避免.
感谢任何帮助。
基本的方法就是写一个systemd服务。该服务可以默认启用,如 yocto 配方 systemd 配置中所定义。服务调用的脚本或应用程序将在 script/application 完成时禁用该服务 - 即。 systemctl disable foo
。因此,该服务将不会 运行 在未来的引导中。
如您所述,rootfs 需要挂载为 rw 才能工作。
一个简单的解决方案是使用包 post/install 脚本,该脚本在 rootfs 时间 运行 自行停止(如果设置了 $D,则退出 1)。这将导致它在第一次启动时 运行。是的,脚本需要重新挂载根文件系统。
我最终做了 shibley 写的。这是详细的方法:
新建图层
将所需图层放在其他图层所在的位置。我的在 stuff
目录中,在构建目录旁边。
进行以下files/directories:
meta_mylayer
├── conf
│ └── layer.conf
└── recipes-core
└── mylayer-initscript
├── initscript.bb
└── files
├── initscript.service
└── initscript.sh
meta_mylayer
是新图层的名称。
让我们在 conf/layer.conf
中定义图层并告诉它在哪里搜索食谱:
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "meta-mylayer"
BBFILE_PATTERN_meta-mylayer := "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-mylayer = "99"
食谱由 .bb 文件的名称定义。这一层只有一个配方,名称为initscript.
initscript.bb
包含配方信息。以下配方将添加我们的 initscript 服务并将实际的安装脚本 initscript.sh
放入 /usr/sbin/
SUMMARY = "Initial boot script"
DESCRIPTION = "Script to do any first boot init, started as a systemd service which removes itself once finished"
LICENSE = "CLOSED"
PR = "r3"
SRC_URI = " \
file://initscript.sh \
file://initscript.service \
"
do_compile () {
}
do_install () {
install -d ${D}/${sbindir}
install -m 0755 ${WORKDIR}/initscript.sh ${D}/${sbindir}
install -d ${D}${systemd_unitdir}/system/
install -m 0644 ${WORKDIR}/initscript.service ${D}${systemd_unitdir}/system
}
NATIVE_SYSTEMD_SUPPORT = "1"
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE_${PN} = "initscript.service"
inherit allarch systemd
install -d
将创建指定路径所需的任何目录,而 install -m 0644
将复制具有 644 权限的指定文件。 ${D}
是目标目录,默认为 ${WORKDIR}/image
创建 systemd 服务定义
我不会详细介绍 systemd 的工作原理,而是粘贴服务定义:
[Unit]
Description=start initscript upon first boot
[Service]
Type=simple
ExecStart=/bin/sh -c 'sleep 5 ; /usr/sbin/initscript.sh'
请注意 /usr/sbin/
处的脚本位置 - 这是上面 do_install
函数的最后一行将复制的位置。
最后,我们的 initscript.sh
脚本本身:
#!/bin/sh
logger "starting initscript"
# do some work here. Mount rootfs as rw if needed.
logger "initscript work done"
#job done, remove it from systemd services
systemctl disable initscript.service
logger "initscript disabled"
注册图层
我们需要注册我们的新图层,以便 bitbake 知道它在那里。
编辑 build/conf/bblayers.conf
文件并将以下行添加到 BASELAYERS
变量:
${TOPDIR}/../stuff/meta-mylayer \
现在 bitbake 识别了我们的层,我们需要将我们的配方添加到图像中。
编辑 build/conf/local.conf
并将 initscript 配方添加到 IMAGE_INSTALL_append
变量。这是添加到 python.
旁边时的样子
IMAGE_INSTALL_append = " python initscript"
运行 构建
运行 像往常一样构建。例如:
bitbake angstrom-lxde-image
在您第一次安装构建和引导后,您的 initscript.sh
将被执行。
谢谢,这很有帮助。我需要添加
[Install]
WantedBy=multi-user.target
到 initscript.service 让它工作
另外,我不知道如何解决rootfs挂载为只读的问题,你可以使用pkg_postinst_ontarget_${PN}
将此添加到您的食谱之一:
pkg_postinst_ontarget_${PN}() {
#!/bin/bash
// bash script you want to run
echo Post Install Script Test > /dev/ttyS1
}
${PN}
将替换为食谱对应的包名。
该脚本只会 运行 一次,在目标机器上第一次启动时作为软件包的 post-install 脚本。
我需要 运行 Yocto 构建的目标 OS 上的脚本。
此脚本需要 运行 作为安装的一部分,因此只能 运行 一次(在整个 OS 安装之后或第一次启动时)。它不能在主机系统上 运行,因为它取决于仅存在于目标上的硬件 IO。
另一个次要的限制是 rootfs 被挂载为只读,但我想这可以通过让脚本重新挂载为 rw 并在执行后再次重新挂载为 r 或类似的东西来避免.
感谢任何帮助。
基本的方法就是写一个systemd服务。该服务可以默认启用,如 yocto 配方 systemd 配置中所定义。服务调用的脚本或应用程序将在 script/application 完成时禁用该服务 - 即。 systemctl disable foo
。因此,该服务将不会 运行 在未来的引导中。
如您所述,rootfs 需要挂载为 rw 才能工作。
一个简单的解决方案是使用包 post/install 脚本,该脚本在 rootfs 时间 运行 自行停止(如果设置了 $D,则退出 1)。这将导致它在第一次启动时 运行。是的,脚本需要重新挂载根文件系统。
我最终做了 shibley 写的。这是详细的方法:
新建图层
将所需图层放在其他图层所在的位置。我的在 stuff
目录中,在构建目录旁边。
进行以下files/directories:
meta_mylayer
├── conf
│ └── layer.conf
└── recipes-core
└── mylayer-initscript
├── initscript.bb
└── files
├── initscript.service
└── initscript.sh
meta_mylayer
是新图层的名称。
让我们在 conf/layer.conf
中定义图层并告诉它在哪里搜索食谱:
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "meta-mylayer"
BBFILE_PATTERN_meta-mylayer := "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-mylayer = "99"
食谱由 .bb 文件的名称定义。这一层只有一个配方,名称为initscript.
initscript.bb
包含配方信息。以下配方将添加我们的 initscript 服务并将实际的安装脚本 initscript.sh
放入 /usr/sbin/
SUMMARY = "Initial boot script"
DESCRIPTION = "Script to do any first boot init, started as a systemd service which removes itself once finished"
LICENSE = "CLOSED"
PR = "r3"
SRC_URI = " \
file://initscript.sh \
file://initscript.service \
"
do_compile () {
}
do_install () {
install -d ${D}/${sbindir}
install -m 0755 ${WORKDIR}/initscript.sh ${D}/${sbindir}
install -d ${D}${systemd_unitdir}/system/
install -m 0644 ${WORKDIR}/initscript.service ${D}${systemd_unitdir}/system
}
NATIVE_SYSTEMD_SUPPORT = "1"
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE_${PN} = "initscript.service"
inherit allarch systemd
install -d
将创建指定路径所需的任何目录,而 install -m 0644
将复制具有 644 权限的指定文件。 ${D}
是目标目录,默认为 ${WORKDIR}/image
创建 systemd 服务定义
我不会详细介绍 systemd 的工作原理,而是粘贴服务定义:
[Unit]
Description=start initscript upon first boot
[Service]
Type=simple
ExecStart=/bin/sh -c 'sleep 5 ; /usr/sbin/initscript.sh'
请注意 /usr/sbin/
处的脚本位置 - 这是上面 do_install
函数的最后一行将复制的位置。
最后,我们的 initscript.sh
脚本本身:
#!/bin/sh
logger "starting initscript"
# do some work here. Mount rootfs as rw if needed.
logger "initscript work done"
#job done, remove it from systemd services
systemctl disable initscript.service
logger "initscript disabled"
注册图层
我们需要注册我们的新图层,以便 bitbake 知道它在那里。
编辑 build/conf/bblayers.conf
文件并将以下行添加到 BASELAYERS
变量:
${TOPDIR}/../stuff/meta-mylayer \
现在 bitbake 识别了我们的层,我们需要将我们的配方添加到图像中。
编辑 build/conf/local.conf
并将 initscript 配方添加到 IMAGE_INSTALL_append
变量。这是添加到 python.
IMAGE_INSTALL_append = " python initscript"
运行 构建
运行 像往常一样构建。例如:
bitbake angstrom-lxde-image
在您第一次安装构建和引导后,您的 initscript.sh
将被执行。
谢谢,这很有帮助。我需要添加
[Install]
WantedBy=multi-user.target
到 initscript.service 让它工作
另外,我不知道如何解决rootfs挂载为只读的问题,你可以使用pkg_postinst_ontarget_${PN}
将此添加到您的食谱之一:
pkg_postinst_ontarget_${PN}() {
#!/bin/bash
// bash script you want to run
echo Post Install Script Test > /dev/ttyS1
}
${PN}
将替换为食谱对应的包名。
该脚本只会 运行 一次,在目标机器上第一次启动时作为软件包的 post-install 脚本。