【发布时间】:2014-12-01 16:40:03
【问题描述】:
我需要将 .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 是否被认为是一个仅限根的应用程序。
我也可以使用 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 块。
最后,我的问题是是否有人知道为什么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 编译器,但它抱怨同样的事情。
【问题讨论】:
-
Mono.Unix在Mono.Posix.dll 中。
标签: linux service mono root daemon