2016-11-04 175 views
1

我需要在由Yocto构建的目标OS上运行脚本。Yocto构建的linux后安装脚本

此脚本需要作为安装的一部分运行,因此必须只运行一次(在整个操作系统安装后或第一次启动后)。它不能在主机系统上运行,因为它取决于仅存在于目标上的硬件IO。

一个额外的小问题是,rootfs被挂载为只读,但我想可以通过将脚本重新挂载为rw并在执行后重新挂载为r或沿着这些行重新挂载来避免。

任何帮助表示赞赏。

回答

4

我最终做了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服务定义

我不会进入太多的细节有关的工作原理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将被执行。

+0

它对我不起作用,文件被传输但服务在启动时不执行。我可以用start选项手动执行它。 –

+0

尝试手动将其添加到自动启动(systemctl enable foo)并查看它是否有效以及发生了什么变化。在/ etc/systemd/system下提供服务文件应该足够了。 – Igor

1

基本的方法是写一个systemd服务。默认情况下,服务可以按照yocto配方系统配置中的定义启用。脚本/应用程序完成时,服务引发的脚本或应用程序将禁用该服务 - 即。 systemctl disable foo。因此,该服务将不会在未来的靴子中运行。

正如您所提到的,rootfs将需要安装为rw才能正常工作。

0

一个简单的解决方案是使用一个封装后/安装脚本,它停止在rootfs时间运行(如果设置了$ D,则退出1)。这将导致它在第一次启动时运行。是的,脚本需要重新安装根目录。

+0

这听起来很有趣。你能详细说明吗?我曾尝试为现有配方制作一个.bbappend,并在该bbappend中使用do_install_append脚本,但它试图在**主机**系统上执行所述脚本,这不是我所需要的。 – Igor

+0

http://www.yoctoproject.org/docs/2.2/dev-manual/dev-manual.html#new-recipe-post-installation-scripts –

0

谢谢,这有帮助。我需要

[Install] WantedBy=multi-user.target

添加到initscript.service得到它的工作