2014-12-01 198 views
0

我需要在嵌入式系統上以最低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編譯器,但它抱怨同樣的事情。

+1

'Mono.Unix'在[Mono.Posix.dll](http://stackoverflow.com/a/8408723/85785)中。 – mythz 2014-12-01 17:15:02

回答

0

mono-service.exe創建一個新的AppDomainApplicationBase是當前目錄。這可能會影響裝配加載。由於您看到這樣的錯誤,我會嘗試啓用MONO_LOG_LEVEL=debug MONO_LOG_MASK=asm和/或strace -e file以查看它們是否提供任何提示。

另外請注意,您可以通過-d切換到mono-service來讓它更改您的目錄。

相關問題