savonet / liquidsoap

Liquidsoap is a statically typed scripting general-purpose language with dedicated operators and backend for all thing media, streaming, file generation, automation, HTTP backend and more.
http://liquidsoap.info
GNU General Public License v2.0
1.39k stars 128 forks source link

Add systemd start script to packages #1997

Open nuess0r opened 2 years ago

nuess0r commented 2 years ago

Is your feature request related to a problem? Please describe. The liquidsoap packages don't provide scripts so that liquidsoap is automatically started after boot or can be monitored as other system services.

Describe the solution you'd like Radio RaBe provides a systemd script that works for me: https://github.com/radiorabe/centos-rpm-liquidsoap/blob/master/liquidsoap%40.service

toots commented 2 years ago

Thanks for this report. I'll look at it shortly.

Kerosel commented 2 years ago

Just for documentation, while working with @nuess0r on #1995, I found this script works great (once I figured out the finer points of systemd unit templates). I briefly experimented with making the liquidsoap scripts behave like daemons (settings.init.daemon.set(true)) and adding "type=forking" to the service configuration... but it behaves strangely and doesn't shut down properly. I think using the "type" default and non-deamonizing the scripts is a fine way to go.

If this is put in place, the logrotate script needs a small tweak:

[...]
  sharedscripts
  postrotate
    sudo systemctl kill --signal SIGUSR1 liquidsoap@\*.service
  endscript

This does the same as the previous start-stop-daemon line did, but through systemd and as a bonus, doesn't require a PID file. I only wonder if it will fail if there are no liquidsoap@ instances running...

toots commented 2 years ago

Hi @Kerosel !

When set to behave as a daemon, liquidsoap does the forking on its own so there's no need to set it in systemd.

However, when using systemd, I would actually advise to do the opposite, i.e. do not ask liquidsoap to daemonize and let systemd handle all the quirks of setting a process as daemon. There's a lot of arcane stuff involved with it and it becomes tricky to track pid file and etc. I believe that, by using systemd, you have a better daemon service.

td;dr: daemons are old fashioned and systemd does a really good job at bringing it to the 221st century.

As for the package scripts, I am a little reluctant to add them because we, as a developer team, do not have a lot of time to maintain multiple elements related to the project. Adding them means, later, fixing issues with them and etc.

Frankly, we would love to welcome a developer interested in maintaining those scripts and taking care of user feedbacks and fixes with them.. 🙂

Kerosel commented 2 years ago

Totally fair take, you have enough to deal with just working on Liquidsoap, you don't need to start maintaining the various different bits and pieces of scripts for specific distributions.

I could be convinced to help maintain scripts... I'm not the most expert person, but I know how to use a search engine to put together a solution. My only worry is feeling like I don't have enough free time and being really good at procrastinating on things. But I could take a shot at helping maintain the systemd service and logrotate scripts and see how things go from there.

toots commented 2 years ago

That would be awesome! The code for the debian packages generated during the CI is here: https://github.com/savonet/liquidsoap/tree/main/.github/debian

Are you familiar with Debian packaging?

Kerosel commented 2 years ago

I've never packaged anything and definitely not done any automatic packaging in GitHub. But I'm totally willing to learn and I tend to catch on to things quickly.

I'll look over the CI code and do some searching on the web, but if you have a specific place I can read up on the process, please send it along. ^_^

toots commented 2 years ago

Okay! It shouldn't be too hard. Also, if you have a script that works we can discuss it and I can show how to integrate it to the build, this won't be the most complicated task.

Kerosel commented 2 years ago

Man, sorry for being gone for so long. Let me see if we can get this going again.

This is the script I've been using, cribbed from the work others have done and suggested here. It has the advantage of handling any script in /etc/liquidsoap with just the single config file.

[Unit]
Description=Liquidsoap
Documentation=http://liquidsoap.fm man:liquidsoap(1)
Requires=sound.target
Wants=network-online.target
After=network-online.target sound.target

[Service]
PermissionsStartOnly=true
RuntimeDirectory=liquidsoap
ExecStartPre=-/bin/mkdir -p /var/log/liquidsoap
ExecStartPre=-/bin/chown liquidsoap /var/log/liquidsoap
ExecStart=/usr/bin/liquidsoap -v /etc/liquidsoap/%i.liq
User=liquidsoap
Group=liquidsoap

[Install]
WantedBy=multi-user.target

I added the RuntimeDirectory line because while systemd doesn't use PID files in the /run directory, the default place for the Unix socket is in /run/liquidsoap/. I went from telnet to Unix sockets and the script wouldn't start after a reboot because /run/liquidsoap/ didn't exist.

I'm also not entirely sure the ExecStartPre lines are necessary... they create the liquidsoap directory under /var/log. It doesn't hurt to have them in there, but if the package creates that directory, it might not be necessary in the systemd configuration.

This lives in /etc/systemd/system, which I think is a good place for it, but I've always been confused by the multiple different locations to put things in Linux, so if someone knows better, let's put it where it should be. It does need an @ sign at the end of the name to signify it's a template (liquidsoap@.service).

Along with that is the updated logrotate config that uses systemd rather than iterating through PID files in the /run directory.

/var/log/liquidsoap/*.log {
  compress
  delaycompress
  rotate 5
  size 300k
  missingok
  notifempty
  sharedscripts
  postrotate
    systemctl kill --signal SIGUSR1 liquidsoap@\*.service
  endscript
}

Because systemd doesn't use PID files and tracks PIDs internally, we have to send the SIGUSR1 signal using systemctl. Using "liquidsoap@" as the service name will send the signal to all* liquidsoap instances that are running (the equivalent of gathering all the PIDs and sending the signal to each one).

This has been working on my server for several months and rotates just like it should.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.