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

时间:2014-12-01 16:40:04

标签: linux service mono root daemon

我需要在嵌入式系统上运行.net C#应用程序(在Windows系统上开发)作为服务/守护程序,安装最少的Ubuntu(没有X,除了ssh之外没有服务器,只有相关软件)。我创建了一个包含行<{p>>的/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机器上发送StopWork()时正常(即执行SIGTERM)。

出于安全考虑,我需要能够以非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块。

最后,我的问题是指某人在未以root身份启动时是否知道mono-service失败的原因。错误消息如下所示,正如我之前提到的,当我使用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 :(得分:0)

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

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