我需要将.net C#应用程序(在Windows上开发)作为一个服务/守护进程运行在嵌入式系统上,只需安装一个最小的Ubuntu (no,除了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机器上发送StopWork()时优雅地死亡(即执行SIGTERM )。
出于安全考虑,我需要能够以非根的形式运行该服务。我创建了一个新用户,并使其成为应用程序写入日志文件的目录的所有者,并将其添加到各个组,以使其能够访问所需的设备文件。然后,root将将应用程序启动为
sudo -u newuser mono-service my-.net-app.exe service或
sudo -u newuser mono my-.net-app.exe interactivemono的第二个选项工作得很好,但是第一个选项与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上编译,说using Mono.Unix;和using Mono.Unix.Native行无效。我还在Windows上安装了Mono,并尝试使用Mono编译器,但它抱怨同样的事情。
发布于 2014-12-01 21:42:01
mono-service.exe创建一个新的AppDomain,ApplicationBase是当前目录。这可能会影响程序集加载。由于您正在看到这样的错误,我将尝试启用MONO_LOG_LEVEL=debug MONO_LOG_MASK=asm和/或strace -e file来查看它们是否提供了任何提示。
还请注意,您可以将-d开关传递给mono-service,让它为您更改目录。
https://stackoverflow.com/questions/27232991
复制相似问题