我需要在由Yocto构建的目标OS上运行脚本。Yocto构建的linux后安装脚本
此脚本需要作为安装的一部分运行,因此必须只运行一次(在整个操作系统安装后或第一次启动后)。它不能在主机系统上运行,因为它取决于仅存在于目标上的硬件IO。
一个额外的小问题是,rootfs被挂载为只读,但我想可以通过将脚本重新挂载为rw并在执行后重新挂载为r或沿着这些行重新挂载来避免。
任何帮助表示赞赏。
我需要在由Yocto构建的目标OS上运行脚本。Yocto构建的linux后安装脚本
此脚本需要作为安装的一部分运行,因此必须只运行一次(在整个操作系统安装后或第一次启动后)。它不能在主机系统上运行,因为它取决于仅存在于目标上的硬件IO。
一个额外的小问题是,rootfs被挂载为只读,但我想可以通过将脚本重新挂载为rw并在执行后重新挂载为r或沿着这些行重新挂载来避免。
任何帮助表示赞赏。
我最终做了shibley写的东西。这里有一个详细的HOWTO:
把所需层无论你的其他层。我的目录是stuff
,位于build目录旁边。
进行以下的文件/目录:
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.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,而是要贴服的定义:
[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
将被执行。
基本的方法是写一个systemd服务。默认情况下,服务可以按照yocto配方系统配置中的定义启用。脚本/应用程序完成时,服务引发的脚本或应用程序将禁用该服务 - 即。 systemctl disable foo
。因此,该服务将不会在未来的靴子中运行。
正如您所提到的,rootfs将需要安装为rw才能正常工作。
一个简单的解决方案是使用一个封装后/安装脚本,它停止在rootfs时间运行(如果设置了$ D,则退出1)。这将导致它在第一次启动时运行。是的,脚本需要重新安装根目录。
这听起来很有趣。你能详细说明吗?我曾尝试为现有配方制作一个.bbappend,并在该bbappend中使用do_install_append脚本,但它试图在**主机**系统上执行所述脚本,这不是我所需要的。 – Igor
http://www.yoctoproject.org/docs/2.2/dev-manual/dev-manual.html#new-recipe-post-installation-scripts –
谢谢,这有帮助。我需要
[Install] WantedBy=multi-user.target
添加到initscript.service得到它的工作
它对我不起作用,文件被传输但服务在启动时不执行。我可以用start选项手动执行它。 –
尝试手动将其添加到自动启动(systemctl enable foo)并查看它是否有效以及发生了什么变化。在/ etc/systemd/system下提供服务文件应该足够了。 – Igor