【问题标题】:Problems running shell script from within .Net Core service daemon on Linux在 Linux 上从 .Net Core 服务守护程序中运行 shell 脚本时出现问题
【发布时间】:2023-03-17 21:47:01
【问题描述】:

我正在尝试从 .Net Core 服务守护进程中执行 .sh 脚本并出现奇怪的行为。脚本的目的是创建一个加密容器,格式化它,设置一些设置,然后挂载它。

我在 Raspberry Pi 4 上的 Raspbian 上使用 .Net Core 3.1.4 版。

问题:我有以下脚本,它创建容器、格式化它、设置设置,然后尝试挂载它。一切似乎都很好,但最后一个命令 mount call 从来没有真正起作用。挂载点无效。

踢球者: 通过服务运行脚本后,如果我打开终端并在那里手动发出安装命令,它会正确安装。然后我可以转到那个挂载点,它显示了大约 10GB 的可用空间,这意味着它正在使用容器。

注意:测试时请确保脚本为chmod +x。您还需要安装 cryptsetup 才能工作。

想法:

我不确定是否缺少某些环境或 PATH 变量以使 shell 脚本正常运行。由于这是一项服务,如果我知道它是什么,我可以编辑 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

【问题讨论】:

    标签: linux asp.net-core encryption raspberry-pi raspbian-buster


    【解决方案1】:

    问题是无法直接从服务中运行mount 命令。通过大量的试验和错误,即使打印 mount 命令的详细信息也会显示没有错误并且不会安装。不向用户提供一些失败消息非常误导。

    解决方案是创建一个Unit 文件“服务”来处理挂载/卸载。下面解释了带我来到这里的鼓舞人心的文章的链接。

    第 1 步:创建单元文件

    关键是.mount 文件需要以与单元文件中的Where= 匹配的模式命名。所以如果你挂载/mnt/content1,你的文件是:

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

    这是我使用的单元文件详细信息。

    [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
    

    最后的步骤:

    您现在可以在专用于mount 和unmount 的新“服务”上发出start/stop。此不会在重启时自动挂载,如果您需要启用该服务来执行此操作。

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

    文章:https://www.golinuxcloud.com/mount-filesystem-without-fstab-systemd-rhel-8/

    【讨论】:

      猜你喜欢
      • 2018-07-31
      • 2011-10-13
      • 2016-11-12
      • 2010-12-08
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-13
      相关资源
      最近更新 更多