首页 文章

在linux中以非root身份运行mono-service

提问于
浏览
0

我需要在嵌入式系统上运行.net C#应用程序(在Windows系统上开发)作为服务/守护进程,安装最少的Ubuntu(没有X,除了ssh之外没有服务器,只有相关软件) . 我创建了一个包含该行的 /etc/init.d 脚本

mono-service my-.net-app.exe service

这很有效 . 还可以选择以交互方式启动应用程序(用于调试目的)

mono my-.net-app.exe interactive

最后一个参数是.NET应用程序的参数,告诉它它是否作为服务运行 . 这大致是以这种方式实现的:

private static void Main(string[] args){
  if(args.Any() && args[0] != null && args[0] == "service"){
    ServiceBase.Run(new[] {(ServiceBase) new MyService()});
  }else{
    try{
      Console.Write("starting app");
      if(StartWork()){
        Console.Write("press any key to exit");
        Console.ReadKey();
      }else{
        Console.WriteLine("starting app failed");
      }
    } // end try
    finally{
      StopWork();
      Console.WriteLine("finished app");
    }
  } // end else
...
} // end Main

public class MyService : ServiceBase{
  static private Thread _worker;

  protected override void OnStart(string[] args){
    _worker = new Thread(() => Program.StartWork(asService: true)); // this asService tells StartWork to not produce console output
    _worker.Start();
  }

  protected override void OnStop(){
    Program.StopWork();
    _worker.Join(1000);
  }
}

此实现的目的是允许应用程序在Linux机器上发送 SIGTERM 时正常(即执行 StopWork() ) .

出于安全原因,我需要能够以非root身份运行该服务 . 我创建了一个新用户并使其成为应用程序写入其日志文件的目录的所有者,并将其添加到各个组以使其可以访问所需的设备文件 . 然后,root将启动应用程序

sudo -u newuser mono-service my-.net-app.exe service

要么

sudo -u newuser mono my-.net-app.exe interactive

mono 的第二个选项运行良好,但第一个选项 mono-service 没有(请参阅下面的错误消息) . 由于它适用于 mono ,因此我确信用户 newuser 具有访问所有相关文件和设备的适当权限 . 我想知道 mono-service 是否被认为是一个只有root的应用程序 .

我也可以使用 mono 选项并抑制控制台输出,如下所示:

private static void Main(string[] args){
  try{
    Console.Write("starting app");
    if(StartWork(consoleoutput)){ // true or false depending on whether the service argument was given
      Console.Write("press any key to exit");
      Console.ReadKey();
    }else{
      Console.WriteLine("starting app failed");
    }
  } // end try
  finally{
    StopWork();
    Console.WriteLine("finished app");
  }
...
} // end Main

但是,当我终止服务(即将SIGTERM发送到 mono 进程)时,它立即停止.net应用程序而不允许它执行 finally 块 .

Finally, my question 是否有人知道为什么 mono-service 在未以root身份启动时失败 . 错误消息如下所示,正如我之前提到的,当我使用 mono 而不是 mono-service 时它不存在 .

ERROR Program [4] [15:03:06.795 01/12/14] Error in Main!
FluentNHibernate.Cfg.FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.

---> NHibernate.HibernateException: Could not create the driver from SAFEmine.DataStore.Database.MonoSqliteDriver, SAFEmine.DataStore, Version=1.3.0.6, Culture=neutral, PublicKeyToken=null. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> NHibernate.HibernateException: The IDbCommand and IDbConnection implementation in the assembly Mono.Data.Sqlite could not be found. Ensure that the assembly Mono.Data.Sqlite is located in the application directory or in the Global Assembly Cache. If the assembly is in the GAC, use <qualifyAssembly/> element in the application configuration file to specify the full name of the assembly.
at NHibernate.Driver.ReflectionBasedDriver..ctor (System.String providerInvariantName, System.String driverAssemblyName, System.String connectionTypeName, System.String commandTypeName) [0x00000] in <filename unknown>:0 
at NHibernate.Driver.ReflectionBasedDriver..ctor (System.String driverAssemblyName, System.String connectionTypeName, System.String commandTypeName) [0x00000] in <filename unknown>:0 
at SAFEmine.DataStore.Database.MonoSqliteDriver..ctor () [0x00000] in <filename unknown>:0 
at (wrapper managed-to-native) System.Reflection.MonoCMethod:InternalInvoke (System.Reflection.MonoCMethod,object,object[],System.Exception&)
at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00000] in <filename unknown>:0

或者,如果我满足 mono 而不是 mono-service ,有没有办法从.net应用程序中捕获 SIGTERM 并优雅地死?我试过这个:https://github.com/ServiceStack/ServiceStack/wiki/Run-ServiceStack-as-a-daemon-on-Linux,但代码无法在Visual Studio上编译,说 using Mono.Unix;using Mono.Unix.Native 行无效 . 我还在Windows上安装了Mono并尝试使用Mono编译器,但它抱怨同样的事情 .

1 回答

  • 0

    mono-service.exe 创建一个新的 AppDomain ,其中 ApplicationBase 是当前目录 . 这可能会影响装配加载 . 由于您看到了这样的错误,我会尝试启用 MONO_LOG_LEVEL=debug MONO_LOG_MASK=asm 和/或 strace -e file 以查看它们是否提供任何提示 .

    另请注意,您可以将 -d 切换到 mono-service 以让它为您更改目录 .

相关问题