Запускать скрипт только при первой загрузке

12

Есть ли в Ubuntu идиоматический способ запуска скрипта только при первой загрузке машины? (EC2).

Роберто Алои
источник

Ответы:

14

Нет. Но вы можете захотеть поместить свой скрипт /etc/init.d/scriptи удалить его самостоятельно:

#!/bin/bash

echo "Bump! I'm your first-boot script."

# Delete me
rm $0
Андрейс Кайников
источник
Обратите внимание, это $0зависит от bash (версия> = 3). В целях совместимости вы можете вместо этого rm /etc/init.d/script
указать
4
$ 0 НЕ относится к bash и поддерживается намного дольше, чем bash 3.x (и поддерживается в Bourne, Korn, zsh и других). Камнем преткновения является то, содержит ли $ 0 полную или относительную спецификацию пути. Вот ссылка на надежный способ получения полного пути, если он вам нужен: stackoverflow.com/questions/4774054/…
Джим Деннис,
7

Создайте файл отслеживания при запуске скрипта. Если файл уже существует, выйдите из сценария.

Том
источник
3
Хотя на первый взгляд это может показаться не таким, но это может быть лучшим решением, чем удаление сценария, поскольку у него есть возможность запустить его снова, если вы захотите.
Мсанфорд
7

Объединение первых двух ответов. Предполагая, что вы называете свой скрипт, /usr/local/bin/firstboot.shставьте его в конце /etc/rc.local(эти скрипты запускаются при каждой загрузке).

#! / Bin / Баш

FLAG = "/ Var / Журнал / firstboot.log"
если [ ! -f $ FLAG]; тогда
   # Поместите здесь ваши предложения инициализации
   echo "Это первая загрузка"

   # следующая строка создает пустой файл, поэтому он не будет запускаться при следующей загрузке
   коснитесь $ FLAG
еще
   эхо "Ничего не делать"
фи
Awi
источник
Это не обязательно работает с sysmtemd. Мне нужно добавить сон 20, чтобы убедиться, что это последний запуск скрипта.
Mrossi
Если вы назовете его /etc/rc.local/99-firstboot.sh, он должен запускаться последним.
JohnDavid
3

Я удивлен результатами, которые я вижу при поиске четко определенного и поддерживаемого хука Ubuntu «первая загрузка». Похоже, толпа Red Hat / Fedora / CentOS уже более десяти лет добивается этого. Ближайший эквивалент Ubuntu - oem-config-firstboot .

Идея просто выполнить rm $0работу воли. Но, технически, есть некоторая интересная семантика. В отличие от большинства других интерпретаторов сценариев в Unix, сценарий оболочки читается и обрабатывается по одной строке / инструкции за раз. Если вы отсоедините ( rm) файл из-под него, то экземпляр оболочки, который обрабатывает этот сценарий, теперь работает с анонимным файлом (любой файл, который открыт, но не связан).

Рассмотрим такой файл:

#!/bin/bash
rm $0
echo "I've removed myself: $0"
ls -l $0
cat <<COMMENTARY
   This is a test.
   I'm still here, because the "here" doc is being fed to 'cat'
   via the anonymous file through the open file descriptor.
   But I cannot be re-exec'd
COMMENTARY
exec $0

Если вы сохраните это в нечто подобное rmself.shи (жесткую) ссылку, что во что-то вроде этого, tstто при запуске ./tstдолжно отобразиться что-то вроде этого:

$ ./tst 
I've removed myself: ./tst
ls: ./tst: No such file or directory
   This is a test.
   I'm still here, because the "here" doc is being fed to 'cat'
   via the anonymous file through the open file descriptor.
   But I cannot be re-exec'd
./tst: line 11: /home/jimd/bin/tst: No such file or directory
./tst: line 11: exec: /home/jimd/bin/tst: cannot execute: No such file or directory

Теперь есть несколько странных возможных угловых случаев в отношении символических ссылок и случаев, когда скрипт вызывался как голое имя (что заставляло оболочку искать $PATHскрипт.

Но кажется, что bash(по крайней мере в версии 3.2) предшествует $0путь, если он искал путь, и в противном случае оставляет $ 0 установленным для любого относительного или абсолютного пути, использованного для вызова скрипта. Кажется, он не делает ни нормализации или разрешения относительных путей, ни символических ссылок.

Вероятно, самой чистой «первой загрузкой» для Ubuntu было бы создать небольшой пакет (.deb), содержащий сценарий для размещения /etc/init.d/firstbootи сценарий после установки, который используется update-rc.dдля связывания этого с уровнем запуска 1 ( /etc/rc1.d) (с помощью команды вроде:) update-rc.d firstboot defaults. .. а затем попросите последнюю строку выполнить деактивацию или удалить что-то вроде:update-rc.d firstboot disable

Вот ссылка на Debian update-rc.d HOWTO

Джим Деннис
источник
0

Вы можете сделать резервную копию текущего rc.local в rc.local.bak

Затем вы можете получить то, что хотите сделать в rc.local, а в конце просто mv /etc/rc.loca.bak /etc/rc.local.

lmojzis
источник
0

Вопрос был о запуске скрипта при первой загрузке EC2. Вы можете использовать cloud-initдля этой цели.

При запуске нового экземпляра EC2 у вас есть возможность определить User dataпод Advanced datails. Если вы разместите cloud-initскрипт там, он будет выполнен только при первой загрузке.

Например, вы можете разместить следующее в User data:

#cloud-config

runcmd:
  - /usr/bin/command1.sh
  - /usr/bin/command2.sh

Вывод будет записан в /var/log/cloud-init-output.log

Cloud-initможет сделать гораздо больше, чем это. Он разработан специально для ранней инициализации облачных экземпляров. Смотрите документы здесь: http://cloudinit.readthedocs.io/en/latest/index.html

Дима Л.
источник