首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在linux中以非root方式运行单服务。

在linux中以非root方式运行单服务。
EN

Stack Overflow用户
提问于 2014-12-01 16:40:03
回答 1查看 3.3K关注 0票数 0

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

代码语言:javascript
复制
mono-service my-.net-app.exe service

这个效果很好。还有一个选项可以以交互方式启动应用程序(用于调试目的)

代码语言:javascript
复制
mono my-.net-app.exe interactive

最后一个参数是.NET应用程序的一个参数,告诉它它是否作为服务运行。这一做法大致是这样实施的:

代码语言:javascript
复制
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将将应用程序启动为

代码语言:javascript
复制
sudo -u newuser mono-service my-.net-app.exe service

代码语言:javascript
复制
sudo -u newuser mono my-.net-app.exe interactive

mono的第二个选项工作得很好,但是第一个选项与mono-service没有关系(请参阅下面的错误消息)。由于它与mono一起工作,我确信用户newuser具有访问所有相关文件和设备的适当权限。我想知道mono-service是否被认为是一个只使用根的应用程序。

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

代码语言:javascript
复制
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块。

最后,我的问题是,是否有人知道为什么mono-service在没有作为root启动时失败。错误消息如下所示,正如我前面提到的,当我使用mono而不是mono-service时,它并不存在。

代码语言:javascript
复制
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上编译,说using Mono.Unix;using Mono.Unix.Native行无效。我还在Windows上安装了Mono,并尝试使用Mono编译器,但它抱怨同样的事情。

EN

回答 1

Stack Overflow用户

发布于 2014-12-01 21:42:01

mono-service.exe创建一个新的AppDomainApplicationBase是当前目录。这可能会影响程序集加载。由于您正在看到这样的错误,我将尝试启用MONO_LOG_LEVEL=debug MONO_LOG_MASK=asm和/或strace -e file来查看它们是否提供了任何提示。

还请注意,您可以将-d开关传递给mono-service,让它为您更改目录。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27232991

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档