Как я могу запустить скрипт при загрузке сразу после монтирования дисков?

Вопрос или проблема

Примечание: я не спрашиваю о запуске службы (или чем-то подобном) после завершения загрузки (я знаю, как это сделать).

Предыстория

Система загружается с SD-карты, на которой находится полная система. К ней подключен либо внешний USB-накопитель, либо SATA SSD – или в некоторых случаях ничего. Я хочу “аутсорсить” некоторые “вещи” на внешний носитель, включая, например, /var/log, если этот носитель доступен. Если он недоступен, должна использоваться “внутренняя” SD-карта. (И если вам интересно: да, это маленький одноплатный компьютер).

Проблема

Очевидно, что прежде чем начнется процесс инициализации, обычная структура каталогов должна уже быть присутствовать. Монтирование файловых систем (из /etc/fstab) осуществляется ядром до этого. Оставаясь на примере /var/log (который не единственный, с которым нужно работать) и одного внешнего накопителя, смонтированного как /mnt/external, когда он доступен:

Как я могу разместить /var/log (например, с помощью символической ссылки) на /mnt/external, если накопитель доступен, но поместить его, например, под /mnt/local в противном случае – безопасным и чистым способом?

Я знаю, что вы “не спрашиваете о запуске службы”, но, к сожалению, природа вопроса требует, чтобы вы поместили свой скрипт в службу и подключили его к нужному месту сразу после того, как диски будут смонтированы.

Я согласен с тем, что вы не запускаете службу, но скрипт, обернутый в эту службу, не должен продолжать работать. Все, что вам нужно от загрузки Linux, это вызвать его в правильный момент, а затем выйти после того, как вы выполните правильную настройку.

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

Правильное место для этого, похоже, одно из:

  • /etc/init.d/checkroot-bootclean.sh: выполняется, когда корневой раздел (/) смонтирован, но до того, как другие разделы станут доступными. Это, вероятно, самое подходящее место для описанного случая, так как цели символических ссылок из других файловых систем уже будут на месте до того, как они будут смонтированы – и особенно, например, аутсорсированный /var/log будет там, когда система начнет записывать логи
  • /etc/init.d/mountall-bootclean.sh: выполняется, когда все локальные файловые системы смонтированы. Здесь, например, будет очищаться /tmp – но здесь я не уверен, нужно ли уже иметь доступ к логам.

Идеально, если наш скрипт будет размещен “между этими двумя”. А в зависимости от системы могут быть и другие места.

На Debian (и его производных, как в моем случае) есть /etc/init/mountall.conf, где настраивается монтирование:

# Этот помощник монтирует файловые системы в правильном порядке по мере того, как устройства
# и точки монтирования становятся доступными.

Этот файл вызывает mountall, чтобы позаботиться о “правильном порядке”, так что некоторые детали можно найти в man mountall – но, к сожалению, ни это, ни /usr/share/doc/mountall/* не дают деталей о том, как подключиться. Выполнение find для mountall дало мне несколько дополнительных файлов, но ни один из них не дал мне дальнейших подсказок – так что, пока я не узнаю что-то еще, вышеупомянутые два места будут “текущими хуками”.


Прежде чем вы спросите: нет, размещение “скрипта запуска” в /etc/rc.X (или эквиваленте с чем-то, что используется вместо SYS-V) не сработает – так как монтирование выполняется ядром до начала процесса инициализации, и эти монтирования должны быть на месте до того, как система начнет записывать, например, логи на диск.

Ответ или решение

Как запустить скрипт при загрузке системы сразу после монтирования дисков

Проблема, с которой вы столкнулись, связана с тем, что необходимо выполнить определенные действия сразу после монтирования файловых систем, но до того, как система начнет писать логи и запускать основные службы. В вашем случае требуется сделать так, чтобы, в зависимости от наличия внешнего устройства (USB-диск или SATA SSD), специальные каталоги, такие как /var/log, могли быть перенаправлены либо на внешнее устройство, либо оставаться на внутреннем SD-карте.

Подходы к решению проблемы

  1. Использование скриптов в /etc/init.d/:

    • Скрипт в checkroot-bootclean.sh: Этот скрипт запускается после монтирования корневой файловой системы. Хотя он не предоставляет полного контроля над состоянием доступности всех внешних устройств, он может быть полезен для первоначальной настройки.
    • Скрипт в mountall-bootclean.sh: Данный скрипт выполняется после монтирования всех локальных файловых систем. Это более подходящее место для выполнения вашего кода, но, не имея дополнительных методов проверки доступности внешних устройств, здесь могут возникнуть сложности.
  2. Скрипты вызова через systemd:

    • На современных дистрибутивах Linux, использующих systemd, вы можете создать единичный файл службы (например, mount-external.service), который будет запускаться при достижении определенной фазы загрузки. Вы можете привязать этот сервис к целям, связанным с монтированием файловых систем, что обеспечит его выполнение в нужный момент.

Пример реализации через systemd

  1. Создайте ваш скрипт, скажем, check_mounts.sh, который проверяет наличие внешнего устройства и перенаправляет /var/log соответственно:

    #!/bin/bash
    
    # Определите mount point
    EXTERNAL_MOUNT="/mnt/external"
    LOCAL_MOUNT="/mnt/local"
    
    # Проверяем, смонтирован ли внешний диск
    if mountpoint -q "$EXTERNAL_MOUNT"; then
       ln -sfn "$EXTERNAL_MOUNT/log" /var/log
    else
       ln -sfn "$LOCAL_MOUNT/log" /var/log
    fi

    Не забудьте дать скрипту права на выполнение:

    chmod +x /path/to/check_mounts.sh
  2. Создайте файл службы для systemd в /etc/systemd/system/mount-external.service:

    [Unit]
    Description=Check and mount external storage
    DefaultDependencies=no
    After=local-fs.target
    
    [Service]
    Type=oneshot
    ExecStart=/path/to/check_mounts.sh
    RemainAfterExit=true
    
    [Install]
    WantedBy=multi-user.target
  3. Включите и запустите ваш сервис:

    systemctl enable mount-external.service

    Это позволит вашему скрипту выполняться на этапе загрузки после монтирования файловых систем.

Заключение

Решение вашей задачи включает в себя использование различных методов для запуска скрипта сразу после монтирования файловых систем. Выбор между init.d и systemd зависит от ваших зависимостей и конфигурации системы. Тем не менее, использование systemd может обеспечить более современный и гибкий подход к управлению процессом загрузки.

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

Оцените материал
Добавить комментарий

Капча загружается...