title: Running mono-service in linux as non-root
body: <p>I need to run a .net C# application (developed on a Windows system) as a service/daemon on an embedded system with a minimal Ubuntu installation (no X, no servers except ssh, only relevant software).  I created an <code>/etc/init.d</code> script containing the line</p>
  
  <pre><code>mono-service my-.net-app.exe service
  </code></pre>
  
  <p>and this worked well.  There is also an option to start the application interactively (for debugging purposes) with </p>
  
  <pre><code>mono my-.net-app.exe interactive
  </code></pre>
  
  <p>The last argument is an argument for the .NET application telling it if it's running as service.  This was implemented roughly this way:</p>
  
  <pre><code>private static void Main(string[] args){
    if(args.Any() &amp;&amp; args[0] != null &amp;&amp; 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(() =&gt; Program.StartWork(asService: true)); // this asService tells StartWork to not produce console output
      _worker.Start();
    }
  
    protected override void OnStop(){
      Program.StopWork();
      _worker.Join(1000);
    }
  }
  </code></pre>
  
  <p>The purpose of this implementation was to allow the application to die gracefully (i.e. to execute <code>StopWork()</code>) upon sending <code>SIGTERM</code> on the linux machine.</p>
  
  <p>For security reasons, I need to be able to run the service as non-root.  I created a new user and made it owner of the directories where the application writes its log files and added it to various groups to give it access to required device files.  Then, root would start the application as</p>
  
  <pre><code>sudo -u newuser mono-service my-.net-app.exe service
  </code></pre>
  
  <p>or</p>
  
  <pre><code>sudo -u newuser mono my-.net-app.exe interactive
  </code></pre>
  
  <p>The second option with <code>mono</code> works well, but the first one with <code>mono-service</code> doesn't (see error message below).  Since it works with <code>mono</code>, I'm confident that the user <code>newuser</code> has appropriate rights to access all relevant files and devices.  I wonder whether <code>mono-service</code> has been conceived as a root-only application.</p>
  
  <p>I could also live with using the <code>mono</code> option and suppressing the console output, like this:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>but then, when I kill the service (i.e. send SIGTERM to the <code>mono</code> process), it stops the .net application immediately without allowing it to execute the <code>finally</code> block.</p>
  
  <p><strong>Finally, my question</strong> is whether someone has an idea why <code>mono-service</code> is failing when not started as root.  The error message is the following and, as I mentioned before, it doesn't exist when I use <code>mono</code> instead of <code>mono-service</code>.</p>
  
  <pre><code>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.
  
  ---&gt; NHibernate.HibernateException: Could not create the driver from SAFEmine.DataStore.Database.MonoSqliteDriver, SAFEmine.DataStore, Version=1.3.0.6, Culture=neutral, PublicKeyToken=null. ---&gt; System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---&gt; 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 &lt;qualifyAssembly/&gt; 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 &lt;filename unknown&gt;:0 
  at NHibernate.Driver.ReflectionBasedDriver..ctor (System.String driverAssemblyName, System.String connectionTypeName, System.String commandTypeName) [0x00000] in &lt;filename unknown&gt;:0 
  at SAFEmine.DataStore.Database.MonoSqliteDriver..ctor () [0x00000] in &lt;filename unknown&gt;:0 
  at (wrapper managed-to-native) System.Reflection.MonoCMethod:InternalInvoke (System.Reflection.MonoCMethod,object,object[],System.Exception&amp;)
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00000] in &lt;filename unknown&gt;:0 
  </code></pre>
  
  <p>Alternatively, if I settle for <code>mono</code> instead of <code>mono-service</code>, is there a way to catch a <code>SIGTERM</code> from within the .net application and to die gracefully?  I tried this: <a href="https://github.com/ServiceStack/ServiceStack/wiki/Run-ServiceStack-as-a-daemon-on-Linux" rel="nofollow">https://github.com/ServiceStack/ServiceStack/wiki/Run-ServiceStack-as-a-daemon-on-Linux</a> , but the code wouldn't compile on Visual Studio saying that the <code>using Mono.Unix;</code> and <code>using Mono.Unix.Native</code> lines were invalid.  I also installed Mono on Windows and tried to use the Mono compiler, but it complained about the same thing.</p>