Проблемы с запуском сценария оболочки из демона службы .Net Core в Linux

Я пытаюсь выполнить .shскрипт из сервисного демона.Net Core и вызывает странное поведение. Цель сценария - создать зашифрованный контейнер, отформатировать его, установить некоторые параметры и затем смонтировать.

Я использую.Net Core версии 3.1.4 на Raspbian на Raspberry Pi 4.

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

Кикер: после запуска сценария через службу, если я открою терминал и вручную введу команду монтирования, он монтируется правильно. Затем я могу перейти к этой точке монтирования, и она покажет ~10 ГБ доступного пространства, что означает, что он использует контейнер.

Примечание. Убедитесь, что сценарийchmod +xпри тестировании. Также для работы вам понадобится установленный cryptsetup.

Мысли:

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

В предыдущих попытках выполнения команд bash мне приходилось устанавливать DISPLAYпеременная, как показано ниже, для правильной работы (из-за необходимости работы с рабочим столом). Для этой проблемы, похоже, это не имеет значения, но если мне нужно установить скрипт как исполняемый, тогда эта команда используется в качестве примера

string chmodArgs = string.Format("DISPLAY=:0.0; export DISPLAY && chmod +x {0}", scriptPath);
chmodArgs = string.Format("-c \"{0}\"", chmodArgs);

Я хотел бы посмотреть, сможет ли кто-нибудь выполнить приведенное ниже и протестировать со своей стороны, чтобы подтвердить и, возможно, помочь найти решение. Спасибо!

#!/bin/bash

#       variables
#       s0f4e7n4r4h8x4j4
#       /usr/sbin/content1
#       content1
#       /mnt/content1
#       10240

#       change the size of M to what the size of container should be
echo "Allocating 10240MB..."
fallocate -l 10240M /usr/sbin/content1
sleep 1

#       using echo with -n passes in the password required for cryptsetup command.  The dash at the end tells cryptsetup to read in from console
echo "Formatting..."
echo -n s0f4e7n4r4h8x4j4 | cryptsetup luksFormat /usr/sbin/content1 - 
sleep 1

echo "Opening..."
echo -n s0f4e7n4r4h8x4j4 | cryptsetup luksOpen /usr/sbin/content1 content1 - 
sleep 1

#       create without journaling
echo "Creating filesystem..."
mkfs.ext4 -O ^has_journal /dev/mapper/content1
sleep 1

#       enable writeback mode
echo "Tuning..."
tune2fs -o journal_data_writeback /dev/mapper/content1
sleep 1

if [ ! -d "/mnt/content1" ]; then
  echo "Creating directory..."
  mkdir -p /mnt/content1
  sleep 1
fi

#       mount with no access time to stop unnecessary writes to disk for just access
echo "Mounting..."
mount /dev/mapper/content1 /mnt/content1 -o noatime
sleep 1

Вот как я выполняю скрипт в.Net

var proc = new System.Diagnostics.Process {
    StartInfo =
        {
            FileName = pathToScript,
            WorkingDirectory = workingDir,
            Arguments = args,
            UseShellExecute = false
        }
};

if (proc.Start())
{
    while (!proc.HasExited)
    {
        System.Threading.Thread.Sleep(33);
    }
}

В Unit использование файла для сервисного демона

[Unit]
Description=Service name

[Service]
ExecStart=/bin/bash -c 'PATH=/sbin/dotnet:$PATH exec dotnet myservice.dll'
WorkingDirectory=/sbin/myservice/
User=root
Group=root
Restart=on-failure
SyslogIdentifier=my-service
PrivateTmp=true

[Install]
WantedBy=multi-user.target

1 ответ

Проблема заключалась в том, что не удалось запустить mountкоманда напрямую из службы. Путем тщательных проб и ошибок, даже при распечатке подробныхmountпокажет, что ошибок НЕТ, и НЕ будет смонтирован. Очень вводит в заблуждение не предоставлять пользователям сообщения об ошибках.

Решение состоит в том, чтобы создать Unitфайл "service" для обработки mount / umount. Ниже поясняется ссылка на вдохновляющую статью, которая привела меня сюда.

Шаг 1. Создайте файл модуля

Ключ - это .mount файл должен быть назван в шаблоне, который соответствует Where=в файле Unit. Итак, если вы монтируете/mnt/content1, ваш файл будет:

sudo nano /etc/systemd/system/mnt-content1.mount

Вот детали файла Unit, которые я использовал.

[Unit]
Description=Mount Content (/mnt/content1)
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target
After=swap.target

[Mount]
What=/dev/mapper/content1
Where=/mnt/content1
Type=ext4
Options=noatime

[Install]
WantedBy=multi-user.target

Шаг 2: перезагрузите systemctl

systemctl daemon-reload

Заключительные шаги:

Теперь вы можете оформить start/stop о новой "услуге", посвященной mount а также unmount. Это не будет автоматически монтироваться при перезагрузке, если вам нужно, вам нужно включить службу для этого.

systemctl start mnt-content1.mount
systemctl stop mnt-content1.mount

Статья: https://www.golinuxcloud.com/mount-filesystem-without-fstab-systemd-rhel-8/

Другие вопросы по тегам