我需要在由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