2016-11-04 211 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得到它的工作