2016-11-04 19 views
1

Мне нужно запустить скрипт на целевой ОС, созданной Yocto.Post-install script на Yocto-built linux

Этот сценарий должен быть запущен как часть установки и, следовательно, должен запускаться только один раз (либо после установки всей ОС, либо при первой загрузке). Он не может быть запущен на хост-системе, поскольку он зависит от аппаратного IO, который существует только на целевой.

Дополнительным, второстепенным ограничением является то, что rootfs монтируется как только для чтения, но я предполагаю, что этого можно избежать, если перезагрузка скрипта выполняется как rw и снова перемонтируется как r после выполнения или что-то в этом направлении.

Любая помощь приветствуется.

ответ

4

Я закончил тем, что сделал shibley. Вот подробный HOWTO:

Создайте новый слой

Поместите нужный слой, где ваши другие слои. Mine находятся в каталоге stuff, рядом с каталогом сборки.

сделать следующие файлы/каталоги:

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" 

Запуск сборки

Run сборки, как вы обычно делаете. Например:

bitbake angstrom-lxde-image 

После установки сборки и загрузки в первый раз, ваш initscript.sh будет выполнен.

+0

это не работает для меня, файлы передаются, но служба не запускается при запуске. Я могу выполнить его вручную с помощью опции start. –

+0

Попробуйте добавить его к автозапуску вручную (systemctl enable foo) и посмотреть, работает ли он и какие изменения. Достаточно иметь служебный файл, доступный в системе/etc/systemd /. – Igor

1

Основной подход - написать службу systemd. Услуга может быть включена по умолчанию, как определено в конфигурации yocto recipe systemd. Сценарий или приложение, вызванное службой, отключит эту службу, когда скрипт/приложение завершится, т.е. systemctl disable foo. Поэтому служба не будет запускаться в будущих ботинках.

Как вы уже упоминали, rootfs потребует установки в качестве rw для этого.

0

Простым решением является использование сценария отправки/установки пакета, который перестает работать в режиме rootfs (выход 1, если задан параметр $ D). Это приведет к запуску при первой загрузке. Да, скрипту нужно будет переустановить root fs.

+0

Это звучит интересно. Не могли бы вы подробнее рассказать? Я попытался использовать .bbappend для существующего рецепта с скриптом do_install_append в этом bbappend, но он попытался выполнить указанный скрипт в ** ** системе **, которая мне не нужна. – 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, чтобы заставить его работать