Проблемы с запуском сценария оболочки из демона службы .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/