Skip to content

jamesdavila/Tmds.Systemd

This branch is 17 commits behind tmds/Tmds.Systemd:master.

Repository files navigation

Travis NuGet

Tmds.Systemd is a .NET Core library for interacting with systemd.

Api

Tmds.Systemd package

This package supports .NET Core 2.0+.

namespace Tmds.Systemd
{
  static class ServiceManager
  {
    // Notify service manager about start-up completion and other service status changes.
    bool Notify(ServiceState state, params ServiceState[] states);
    // Instantiate Sockets for the file descriptors passed by the service manager.
    Socket[] GetListenSockets();
    // Whether the process is running as part of a unit.
    bool IsRunningAsService;
    // Unique identifier of the runtime cycle of the unit.
    string InvocationId;
  }
  static class Journal
  {
    // Returns whether the journal service can be available.
    bool IsSupported { get; }
    // Returns whether the journal service is currently available.
    bool IsAvailable { get; }
    // The syslog identifier added to each log message.
    SyslogIdentifier { get; set; } = "dotnet";
    // Obtain a cleared JournalMessage. The Message must be Disposed to return it.
    JournalMessage GetMessage();
    // Submit a log entry to the journal.
    LogResult Log(LogFlags flags, JournalMessage message);
  }
  enum LogFlags
  { None,
    // Log levels.
    Emergency, ..., Debug,
    // Drop message instead of blocking.
    DropWhenBusy
  }
  enum LogResult
  { Success, UnknownError, NotAvailable, NotSupported, ... }
  class JournalMessage : IDisposable
  {
    // Appends a field to the message.
    JournalMessage Append(string name          , Type value);
    JournalMessage Append(JournalFieldName name, Type value);
  }
  // Represents a valid journal field name.
  struct JournalFieldName
  {
    static readonly JournalFieldName Priority;
    static readonly JournalFieldName SyslogIdentifier;
    static readonly JournalFieldName Message;
    // Implicit conversion from string. Throws when name is not valid.
    static implicit operator JournalFieldName(string str);
  }
}

Tmds.Systemd.Logging package

This package allows to easly add journal logging to an ASP.NET Core application by adding the following line to the host building step:

This package supports .NET Core 2.1+.

         public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
             WebHost.CreateDefaultBuilder(args)
+            .ConfigureLogging(_ =>  _ .AddJournal())
             .UseStartup<Startup>();
     }

The logging can be configured with the following options:

class JournalLoggerOptions
{
  // Drop messages instead of blocking.
  bool DropWhenBusy { get; set; }
  // The syslog identifier added to each log message.
  string SyslogIdentifier { get; set; }
}

The logging added is structured logging. For example, these entries are stored for a GET request:

{
	"PRIORITY" : "6",
	"SYSLOG_IDENTIFIER" : "dotnet",
	"LOGGER" : "Microsoft.AspNetCore.Hosting.Internal.WebHost",
	"EVENTID" : "1",
	"MESSAGE" : "Request starting HTTP/1.1 GET http://localhost:5000/  ",
	"PROTOCOL" : "HTTP/1.1",
	"METHOD" : "GET",
	"SCHEME" : "http",
	"HOST" : "localhost:5000",
	"PATHBASE" : "",
	"PATH" : "/",
	"QUERYSTRING" : "",
	"REQUESTPATH" : "/",
	"CONNECTIONID" : "0HLDSN5JGSU79",
	"REQUESTID" : "0HLDSN5JGSU79:00000001",
}
{
	"PRIORITY" : "6",
	"SYSLOG_IDENTIFIER" : "dotnet",
	"LOGGER" : "Microsoft.AspNetCore.Hosting.Internal.WebHost",
	"EVENTID" : "2",
	"STATUSCODE" : "307",
	"REQUESTPATH" : "/",
	"CONNECTIONID" : "0HLDSN5JGSU79",
	"REQUESTID" : "0HLDSN5JGSU79:00000001",
	"MESSAGE" : "Request finished in 10.9215ms 307 ",
	"ELAPSEDMILLISECONDS" : "10.9215",
}

To follow the journal logging live you can use this command journalctl -f -t dotnet -o json-pretty | grep -v \"_.

Example

Create the application:

$ dotnet new console -o MyDaemon
$ cd MyDaemon

To use a daily build, add the myget NuGet feed to, NuGet.Config.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="tmds" value="https://www.myget.org/F/tmds/api/v3/index.json" />
  </packageSources>
</configuration>

Add the package reference to MyDaemon.csproj.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Tmds.Systemd" Version="0.5.0-*"/>
    <PackageReference Include="Tmds.Systemd.Logging" Version="0.5.0-*"/>
  </ItemGroup>
</Project>

Restore the dependency:

$ dotnet restore

Implement the daemon in Program.cs.

using System;
using static System.Threading.Thread;
using static System.Console;
using Tmds.Systemd;

namespace MyDaemon
{
    class Program
    {
        static void Main(string[] args)
        {
            Sleep(2000);
            ServiceManager.Notify(ServiceState.Ready);
            while (true)
            {
                foreach (var status in new [] { "Doing great", "Everything fine", "Still running" })
                {
                    ServiceManager.Notify(ServiceState.Status(status));
                    Sleep(5000);
                }
            }
        }
    }
}

Publish the application:

$ dotnet publish -c Release

Create a user and folder for our daemon:

# useradd -s /sbin/nologin mydaemon
# mkdir /var/mydaemon

Now we copy the application in the folder:

# cp -r ./bin/Release/netcoreapp2.0/publish/* /var/mydaemon
# chown -R mydaemon:mydaemon /var/mydaemon

Create a systemd service file:

# touch /etc/systemd/system/mydaemon.service
# chmod 664 /etc/systemd/system/mydaemon.service

Add this content to the file mydaemon.service.

[Unit]
Description=My .NET Core Daemon

[Service]
Type=notify
WorkingDirectory=/var/mydaemon
ExecStart=/opt/dotnet/dotnet MyDaemon.dll
Restart=always
RestartSec=10
SyslogIdentifier=mydaemon
User=mydaemon

[Install]
WantedBy=multi-user.target

The Type=notify indicates the application will signal when it is ready.

Start the service:

# systemctl start mydaemon

Notice the command blocks until it gets the Ready notification.

When we query the status of the daemon, we can see the Status notifications.

$ watch systemctl status mydaemon

About

.NET Core library for interacting with systemd

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 100.0%