我需要在嵌入式系統上以最低Ubuntu安裝方式運行.net C#應用程序(在Windows系統上開發)作爲服務/守護程序(不包括X,除服務器外SSH,只有相關的軟件)。我創建了一個/etc/init.d
腳本,其中包含該行以非root用戶身份在linux中運行mono-service
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);
}
}
這種實現的目的是允許應用程序(即,執行StopWork()
)於Linux機器上發送SIGTERM
正常死亡。
出於安全原因,我需要能夠以非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](http://stackoverflow.com/a/8408723/85785)中。 – mythz 2014-12-01 17:15:02