9.6. Настройка и использование загрузочных скриптов System V

9.6.1. Как работают загрузочные скрипты System V?

В Linux используется специальное средство загрузки под названием SysVinit, основанное на концепции уровней выполнения (run-levels). Его настройка может сильно отличаться от одной системы к другой, и корректная работа в одном дистрибутиве Linux, не гарантирует работоспособность в LFS. LFS работает по-своему, но соблюдает общепринятые стандарты.

SysVinit (в дальнейшем именуемый «init») работает по схеме уровней выполнения. Существует семь (пронумерованных от 0 до 6) уровней выполнения (на самом деле уровней больше, но они предназначены для особых случаев и обычно не используются. Подробности смотрите в руководстве init(8)), и каждый из них соответствует действиям, которые компьютер должен выполнить при запуске. Уровень выполнения по умолчанию — 3. Ниже приведены описания различных уровней в том виде, в каком они реализованы в LFS:

0: выключение компьютера
1: однопользовательский режим
2: зарезервировано для настройки, в остальном аналогично 3
3: многопользовательский режим с поддержкой сети
4: зарезервировано для настройки, в остальном аналогично 3
5: то же, что и 4, обычно используется для входа в систему с графическим интерфейсом (например, 
gdm от GNOME или lxdm от LXDE)
6: перезагрузка компьютера

[Примечание]

Примечание

Раньше, много лет назад, уровень выполнения 2 обозначался как "многопользовательский режим без поддержки сети", тогда несколько пользователей могли войти в систему, подключившись через последовательные порты. В сегодняшних условиях это не имеет смысла, и мы обозначаем этот уровень как "зарезервировано".

9.6.2. Настройка Sysvinit

Во время инициализации ядра первая запущенная программа указывается либо в командной строке, либо по умолчанию в init. Эта программа читает файл инициализации /etc/inittab. Создайте этот файл:

cat > /etc/inittab << "EOF"
# Begin /etc/inittab

id:3:initdefault:

si::sysinit:/etc/rc.d/init.d/rc S

l0:0:wait:/etc/rc.d/init.d/rc 0
l1:S1:wait:/etc/rc.d/init.d/rc 1
l2:2:wait:/etc/rc.d/init.d/rc 2
l3:3:wait:/etc/rc.d/init.d/rc 3
l4:4:wait:/etc/rc.d/init.d/rc 4
l5:5:wait:/etc/rc.d/init.d/rc 5
l6:6:wait:/etc/rc.d/init.d/rc 6

ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

su:S06:once:/sbin/sulogin
s1:1:respawn:/sbin/sulogin

1:2345:respawn:/sbin/agetty --noclear tty1 9600
2:2345:respawn:/sbin/agetty tty2 9600
3:2345:respawn:/sbin/agetty tty3 9600
4:2345:respawn:/sbin/agetty tty4 9600
5:2345:respawn:/sbin/agetty tty5 9600
6:2345:respawn:/sbin/agetty tty6 9600

# End /etc/inittab
EOF

Пояснения по содержимому этого файла инициализации находится на справочной странице inittab. Для LFS ключевой командой является rc. В приведенном выше файле инициализации, rc будет выполнять все сценарии, начинающиеся с символа S в каталоге /etc/rc.d/rcS.d, за которыми следуют все скрипты, начинающиеся с S в каталоге /etc/rc.d/rc?.d, где знак вопроса задается значением initdefault.

Для удобства, скрипт rc читает функции из библиотеки /lib/lsb/init-functions. Эта библиотека также читает необязательный файл конфигурации /etc/sysconfig/rc.site. Любой из параметров файла конфигурации системы, описанный в последующих разделах, можно поместить в этот файл, что позволит объединить все системные параметры в одном файле.

Для удобства отладки скрипт functions также записывает весь вывод в /run/var/bootlog. Поскольку каталог /run является tmpfs, этого файла может не быть при загрузке, однако его содержимое добавляется к файлу /var/log/boot.log по окончании процесса загрузки.

9.6.2.1. Изменение уровней выполнения

Изменить уровень выполнения можно с помощью команды init <runlevel>, где <runlevel> - это целевой уровнем выполнения. Например, чтобы перезагрузить компьютер, пользователь должен выполнить команду init 6, которая является псевдонимом для команды reboot. Аналогично, init 0 является псевдонимом для команды halt.

В каталоге /etc/rc.d есть ещё несколько каталогов, которые выглядят как rc?.d (где ? - номер уровня выполнения), все они содержат ряд символических ссылок. Некоторые начинаются с K, другие начинаются с S, и все они содержат две цифры после начальной буквы. K означает остановить (убить) службу, а S означает запустить службу. Числа определяют порядок выполнения сценариев от 00 до 99—чем меньше число, тем раньше он запустится. Когда init переключается на другой уровень выполнения, соответствующие службы запускаются или останавливаются в зависимости от выбранного уровня.

Реальные скрипты находятся в каталоге /etc/rc.d/init.d. Они выполняют фактическую работу, и символические ссылки указывают на них. Ссылки К и S указывают на один и тот же скрипт в /etc/rc.d/init.d. Это связано с тем, что скрипты могут вызываться с разными параметрами, такими как start, stop, restart, reload, и status. Когда встречается ссылка K, соответствующий скрипт запускается с аргументом stop. Когда встречается S-ссылка, соответствующий скрипт запускается с аргументом start.

Ниже приведено описание к аргументам скриптов:

start

Служба запущена.

stop

Служба остановлена.

restart

Служба остановлена и снова запущена.

reload

Конфигурация сервиса обновлена. Используется после изменения файла конфигурации службы, когда перезапуск не требуется.

status

Сообщает, запущена ли служба и с какими ИД процессов.

Не стесняйтесь изменять работу процесса загрузки (в конце концов, это ваша собственная система LFS). Приведенные здесь файлы являются примером того, как это можно сделать.

9.6.3. Загрузочные скрипты Udev

Инит-скрипт /etc/rc.d/init.d/udev запускает udevd, который инициализирует все устройства "холодного подключения", которые уже были созданы ядром, и ожидает выполнения всех правил. Скрипт также отключает обработчик uevent по умолчанию /sbin/hotplug. Это сделано потому, что ядру больше не нужно обращаться к внешнему бинарному файлу. Вместо этого udevd будет прослушивать сокет netlink для событий uevents, которые вызывает ядро.

Инит-скрипт /etc/rc.d/init.d/udev_retry решает задачу повторного запуска событий для подсистем, правила которых могут зависеть от файловых систем, которые не монтируются до запуска скрипта mountfs (в частности, его вызывают /usr и /var). Этот скрипт запускается после скрипта mountfs, поэтому правила (при повторном запуске) должны выполняться успешно. Он настраивается из файла /etc/sysconfig/udev_retry; любые слова в этом файле, кроме комментариев, являются именами подсистем, которые могут выполняться повторно. Чтобы найти подсистему устройства, используйте udevadm info --attribute-walk <device>, где <device> - это абсолютный путь в /dev или /sys, такой как /dev/sr0 или /sys/class/rtc.

Для получения информации о загрузке модуля ядра и udev смотрите Раздел 9.3.2.3, «Загрузка модуля».

9.6.4. Настройка системного времени

Скрипт setclock считывает время с аппаратных часов, также известных как часы BIOS или CMOS (Complementary Metal Oxide Semiconductor). Если на аппаратных часах установлено время UTC (всемирное скоординированное время), этот скрипт преобразует полученное значение в локальное время, используя файл /etc/localtime (который сообщает программе hwclock, в какой временной зоне находится пользователь). Невозможно определить, установлено на аппаратных часах UTC или же локальное время, поэтому необходимо указать его вручную.

Скрипт setclock запускается системой udev при загрузке, когда ядро определяет возможности аппаратного обеспечения. Также его можно запустить вручную с параметром stop, чтобы сохранить системное время в аппаратные часы CMOS.

Если Вы не можете вспомнить, установлено на аппаратных часах UTC или локальное время, запустите команду hwclock --localtime --show. Она отобразит текущее время в соответствии с аппаратными часами. Если оно совпадает с тем, что показывают ваши настенные/наручные часы, значит на часах CMOS установлено локальное время. Если вывод hwclock не совпадает с локальным временем, скорее всего, это UTC. Проверьте это, добавляя или вычитая правильное смещение к времени, выводимому hwclock. Например, если ваш часовй пояс это MSK, так же известный как GMT +0300, то нужно вычесть три часа из локального времени.

Измените значение переменной UTC ниже на 0 (ноль), если на аппаратных часах установлено НЕ UTC.

Создайте новый файл /etc/sysconfig/clock выполнив:

cat > /etc/sysconfig/clock << "EOF"
# Begin /etc/sysconfig/clock

UTC=1

# Set this to any options you might need to give to hwclock,
# such as machine hardware clock type for Alphas.
CLOCKPARAMS=

# End /etc/sysconfig/clock
EOF

Хороший совет, объясняющий, как обращаться с временем в LFS, доступен по адресу https://mirror.linuxfromscratch.ru/hints/downloads/files/time.txt. Там объясняются такие вопросы, как часовые пояса, UTC и переменная окружения TZ.

[Примечание]

Примечание

Параметры CLOCKPARAMS и UTC также могут быть указаны в файле /etc/sysconfig/rc.site.

9.6.5. Настройка консоли Linux

Эта секция описывает настройку скрипта console, который устанавливает раскладку клавиатуры, шрифт консоли и уровень подробности информации, выводимой ядром на консоль. Если Вы не планируете использовать символы, не соответствующие стандарту ASCII (например, знак копирайта, символы фунта и евро), и собираетесь печатать только в английской раскладке, то можете пропустить большую часть секции. Без файла конфигурации (или эквивалентных настроек в rc.site), скрипт console не будет ничего делать.

Скрипт console считывает конфигурацию из файла /etc/sysconfig/console. Решите для себя, какую раскладку клавиатуры и какой шрифт намерены использовать. В этом также могут помочь различные HOWTO для конкретных языков, смотрите https://tldp.org/HOWTO/HOWTO-INDEX/other-lang.html. Если вы все еще сомневаетесь, посмотрите в каталогах /usr/share/keymaps и /usr/share/consolefonts допустимые раскладки и экранные шрифты. Прочтите справочные страницы loadkeys(1) и setfont(8), чтобы определить правильные аргументы для этих программ.

Файл /etc/sysconfig/console должен содержать строки вида: ПЕРЕМЕННАЯ="значение". Допустимы следующие переменные:

LOGLEVEL

Эта переменная задает уровень подробности сообщений, посылаемых ядром на системную консоль. Значение этой переменной передается в качестве аргумента утилите dmesg -n. Допустимы уровни от "1" (нет сообщений) до "8". По умолчанию "7".

KEYMAP

Эта переменная указывает аргументы для программы loadkeys, обычно это имя загружаемой раскладки, например, «it». Если эта переменная не установлена, загрузочный скрипт не будет запускать программу loadkeys, и будет использоваться раскладка по умолчанию. Обратите внимание, что некоторые раскладки имеют несколько версий с одним и тем же именем (cz и его варианты в qwerty/ и qwertz/, es в olpc/ и qwerty/ и trf в fgGIod/ и qwerty/). В этих случаях также следует указать родительский каталог (например, qwerty/es), чтобы обеспечить загрузку правильной раскладки.

KEYMAP_CORRECTIONS

Эта (крайне редко используемая) переменная задает аргументы для второго вызова программы loadkeys. Она полезна, если стандартная раскладка вас не совсем устраивает и необходимо внести небольшую корректировку. Например, чтобы добавить символ евро в раскладку, которая его не содержит, присвойте этой переменной значение «euro2».

FONT

Эта переменная определяет аргументы для программы setfont. Обычно она включает в себя имя шрифта «-m» и имя загружаемой таблицы символов. Например, чтобы загрузить шрифт «lat1-16» вместе с таблицей символов «8859-1» (подходящий для США), установите эту переменную в «lat1-16 -m 8859-1». В режиме UTF-8 ядро использует таблицу символов для преобразования 8-битных кодов клавиш в раскладку UTF-8, поэтому аргумент параметра "-m" должен быть указывать кодировку таблицы символов в раскладке.

UNICODE

Присвойте этой переменной значение «1», «yes» или «true», чтобы переключить консоль в режим UTF-8. Это полезно при использовании локали, основанной на UTF-8, и не рекомендуется в иных случаях.

LEGACY_CHARSET

Для многих раскладок клавиатуры в пакете Kbd не существует готового Unicode-варианта. Скрипт console будет на лету конвертировать имеющуюся раскладку в UTF-8, если присвоить этой переменной имя доступной не-UTF-8 раскладки.

Несколько примеров:

  • Для не-Unicode настройки необходимы только переменные KEYMAP и FONT. Например, для польских пользователей может подойти такой вариант:

    cat > /etc/sysconfig/console << "EOF"
    # Begin /etc/sysconfig/console
    
    KEYMAP="pl2"
    FONT="lat2a-16 -m 8859-2"
    
    # End /etc/sysconfig/console
    EOF
  • Как упоминалось выше, иногда бывает необходимо подкорректировать раскладку. Следующий пример добавляет символ евро к немецкой раскладке:

    cat > /etc/sysconfig/console << "EOF"
    # Begin /etc/sysconfig/console
    
    KEYMAP="de-latin1"
    KEYMAP_CORRECTIONS="euro2"
    FONT="lat0-16 -m 8859-15"
    UNICODE="1"
    
    # End /etc/sysconfig/console
    EOF
  • Ниже приведен пример с поддержкой Unicode для болгарского языка, где существует стандартная раскладка UTF-8:

    cat > /etc/sysconfig/console << "EOF"
    # Begin /etc/sysconfig/console
    
    UNICODE="1"
    KEYMAP="bg_bds-utf8"
    FONT="LatArCyrHeb-16"
    
    # End /etc/sysconfig/console
    EOF
  • Из-за использования 512-символьного шрифта LatArCyrHeb-16 в предыдущем примере, яркие цвета больше не доступны в консоли Linux, если используется фреймбуфер. Если Вы хотите использовать яркие цвета без фреймбуфера и можете обходиться без символов, не относящихся к вашему языку, тогда можно использовать специфичный для вашего языка 256-символьный шрифт, как показано ниже:

    cat > /etc/sysconfig/console << "EOF"
    # Begin /etc/sysconfig/console
    
    UNICODE="1"
    KEYMAP="bg_bds-utf8"
    FONT="cyr-sun16"
    
    # End /etc/sysconfig/console
    EOF
  • Следующий пример демонстрирует автоматическое преобразование раскладки из ISO-8859-15 в UTF-8 и включает "мертвые" клавиши в режиме Unicode:

    cat > /etc/sysconfig/console << "EOF"
    # Begin /etc/sysconfig/console
    
    UNICODE="1"
    KEYMAP="de-latin1"
    KEYMAP_CORRECTIONS="euro2"
    LEGACY_CHARSET="iso-8859-15"
    FONT="LatArCyrHeb-16 -m 8859-15"
    
    # End /etc/sysconfig/console
    EOF
  • Некоторые раскладки включают в себя "мертвые" клавиши (то есть клавиши, нажатие которых само по себе не приводит к появлению на экране символа, но которые влияют на символ, генерируемый следующей клавишей) или определяют слияние символов (например: «нажмите Ctrl+. A E чтобы получить Æ» в раскладке по умолчанию). Linux-5.19.2 правильно интерпретирует "мертвые" клавиши и слияния, только когда исходные символы имеют 8-битные коды. Эта особенность не влияет на раскладки для европейских языков, поскольку в них "сливаются" два ASCII-символа или добавляются подчеркивания к неподчеркнутым ASCII-символам. Однако, в режиме UTF-8 могут быть проблемы, например, для греческого языка, когда необходимо подчеркнуть символ «alpha». Решением в этой ситуации будет отказ от использования UTF-8 или установка графической системы X Window, не имеющих подобных ограничений.

  • Для китайского, японского, корейского и некоторых других языков невозможно насторить консоль Linux так, чтобы она отображала все необходимые символы. Пользователи, которым требуются эти языки, должны установить систему X Window, шрифты, покрывающие необходимый диапазон символов, и правильный метод ввода (например, SCIM, он поддерживает большое число разнообразных языков).

[Примечание]

Примечание

Файл /etc/sysconfig/console управляет только локализацией текстовой консоли Linux. Он никак не влияет на настройки раскладки клавиатуры и шрифтов в системе X Window, в сессиях SSH или на последовательном терминале. В этих ситуациях ограничения, описанные в двух расположенных выше абзацах, не применяются.

9.6.6. Создание файлов при загрузке

Иногда необходимо создавать файлы во время загрузки. Например, часто требуется каталог /tmp/.ICE-unix . Это можно сделать, создав запись в скрипте /etc/sysconfig/createfiles. Формат этого файла описан в комментариях файла конфигурации по умолчанию.

9.6.7. Настройка скрипта sysklogd

Скрипт sysklogd вызывает программу syslogd как часть инициализации System V. Параметр -m 0 отключает периодическую (по умолчанию - каждые 20 минут) запись временных меток в файлы журналов, производимую syslogd. Если Вам необходимо включить периодическую запись временных меток, отредактируйте файл /etc/sysconfig/rc.site и присвойте переменной SYSKLOGD_PARMS требуемое значение. Например, чтобы сбросить все параметры, присвойте переменной пустое значение:

SYSKLOGD_PARMS=

Дополнительные параметры смотрите в man syslogd.

9.6.8. Файл rc.site

Необязательный файл /etc/sysconfig/rc.site содержит настройки, автоматически применяемые всеми загрузочными скриптами. Этот файл может содержать парамеры, обычно указываемые в файлах hostname, console и clock из каталога /etc/sysconfig/. Если значение одной и той же переменной присваивается и в одном из этих файлов, и в rc.site, приоритет имеет значение из специализированного файла.

rc.site также содержит параметры, которые могут настраивать другие аспекты процесса загрузки. Установка переменной IPROMPT позволит выборочно запускать загрузочные скрипты. Другие параметры описаны в комментариях к файлу. Версия файла по умолчанию выглядит следующим образом:

# rc.site
# Optional parameters for boot scripts.

# Distro Information
# These values, if specified here, override the defaults
#DISTRO="Linux From Scratch" # The distro name
#DISTRO_CONTACT="lfs-dev@lists.linuxfromscratch.org" # Bug report address
#DISTRO_MINI="LFS" # Short name used in filenames for distro config

# Define custom colors used in messages printed to the screen

# Please consult `man console_codes` for more information
# under the "ECMA-48 Set Graphics Rendition" section
#
# Warning: when switching from a 8bit to a 9bit font,
# the linux console will reinterpret the bold (1;) to
# the top 256 glyphs of the 9bit font.  This does
# not affect framebuffer consoles

# These values, if specified here, override the defaults
#BRACKET="\\033[1;34m" # Blue
#FAILURE="\\033[1;31m" # Red
#INFO="\\033[1;36m"    # Cyan
#NORMAL="\\033[0;39m"  # Grey
#SUCCESS="\\033[1;32m" # Green
#WARNING="\\033[1;33m" # Yellow

# Use a colored prefix
# These values, if specified here, override the defaults
#BMPREFIX="      "
#SUCCESS_PREFIX="${SUCCESS}  *  ${NORMAL} "
#FAILURE_PREFIX="${FAILURE}*****${NORMAL} "
#WARNING_PREFIX="${WARNING} *** ${NORMAL} "

# Manually seet the right edge of message output (characters)
# Useful when resetting console font during boot to override
# automatic screen width detection
#COLUMNS=120

# Interactive startup
#IPROMPT="yes" # Whether to display the interactive boot prompt
#itime="3"    # The amount of time (in seconds) to display the prompt

# The total length of the distro welcome string, without escape codes
#wlen=$(echo "Welcome to ${DISTRO}" | wc -c )
#welcome_message="Welcome to ${INFO}${DISTRO}${NORMAL}"

# The total length of the interactive string, without escape codes
#ilen=$(echo "Press 'I' to enter interactive startup" | wc -c )
#i_message="Press '${FAILURE}I${NORMAL}' to enter interactive startup"

# Set scripts to skip the file system check on reboot
#FASTBOOT=yes

# Skip reading from the console
#HEADLESS=yes

# Write out fsck progress if yes
#VERBOSE_FSCK=no

# Speed up boot without waiting for settle in udev
#OMIT_UDEV_SETTLE=y

# Speed up boot without waiting for settle in udev_retry
#OMIT_UDEV_RETRY_SETTLE=yes

# Skip cleaning /tmp if yes
#SKIPTMPCLEAN=no

# For setclock
#UTC=1
#CLOCKPARAMS=

# For consolelog (Note that the default, 7=debug, is noisy)
#LOGLEVEL=7

# For network
#HOSTNAME=mylfs

# Delay between TERM and KILL signals at shutdown
#KILLDELAY=3

# Optional sysklogd parameters
#SYSKLOGD_PARMS="-m 0"

# Console parameters
#UNICODE=1
#KEYMAP="de-latin1"
#KEYMAP_CORRECTIONS="euro2"
#FONT="lat0-16 -m 8859-15"
#LEGACY_CHARSET=

9.6.8.1. Настройка скриптов загрузки и завершения работы

Загрузочные скрипты LFS загружают и завершают работу системы довольно эффективно, но есть несколько настроек, которые вы можете внести в файл rc.site, чтобы еще больше повысить скорость и настроить сообщения в соответствии с вашими предпочтениями. Чтобы сделать это, измените настройки в приведенном выше файле /etc/sysconfig/rc.site.

  • Во время работы загрузочного скрипта udev происходит вызов udev settle, для завершения которого требуется некоторое время. Это время может и не потребоваться в зависимости от конфигурации устройств в системе. Если у вас имеются только простые разделы и одна сетевая карта, процессу загрузки, вероятно, не нужно будет ждать завершения работы этой команды. Чтобы пропустить её, установите переменную OMIT_UDEV_SETTLE=y.

  • Скрипт загрузки udev_retry также по умолчанию запускает udev settle. Команда требуется только тогда, когда каталог /var смонтирован в отдельный раздел. Это связано с тем, что часам нужен доступ к файлу /var/lib/hwclock/adjtime. Пропустите команду, установив переменную OMIT_UDEV_RETRY_SETTLE=y.

  • По умолчанию проверка файловой системы выполняется в "тихом" режиме. Это может показаться задержкой во время процесса загрузки. Чтобы включить вывод fsck, установите переменную VERBOSE_FSCK=y.

  • При перезагрузке вы, возможно, захотите полностью пропустить проверку файловой системы, fsck. Чтобы сделать это, либо создайте файл /fastboot, либо перезагрузите систему командой /sbin/shutdown -f -r now. С другой стороны, вы можете принудительно проверить все файловые системы, создав /forcefsck или запустив shutdown с параметром -F вместо -f.

    Установка переменной FASTBOOT=y отключит fsck во время процесса загрузки до тех пор, пока она не будет удалена. Это не рекомендуется делать на постоянной основе.

  • Обычно все файлы в каталоге /tmp удаляются во время загрузки. В зависимости от количества имеющихся файлов или каталогов это может привести к заметной задержке в процессе загрузки. Чтобы пропустить удаление этих файлов, установите переменную SKIPTMPCLEAN=y.

  • Во время завершения работы, init отправляет сигнал TERM каждой запущенной программе (например, agetty), ожидает установленное время (по умолчанию 3 секунды), посылает каждому процессу сигнал завершения(KILL) и снова ждёт. Этот процесс повторяется в сценарии sendsignals для любых процессов, которые не завершаются их собственными скриптами. Задержка для init может быть установлена путем передачи параметра. Например, чтобы устранить задержку в init, передайте параметр -t0 при выключении или перезагрузке (например, /sbin/shutdown -t0 -r now). Задержку для скрипта sendsignals можно пропустить, установив параметр KILLDELAY=0.