1

Background

I want to change some options of Pure-FTPD. Since it has no config file, I need to add command line arguments. My system is Debian Stretch, which uses systemd.


What I tried

There is no pure-ftpd.service file in /etc/systemd/* nor in /usr/lib/systemd/*. I ran updatedb and then locate pure-ftpd which gave no results. Running systemctl status pure-ftpd (or other commands such as restart) works fine.

Finally I found a way to make edits: systemctl edit pure-ftpd. As suggested by another answer on this site, I typed [Service] \n ExecStart=/usr/sbin/pure-ftpd -my options and hit :wq. Systemd reloads the service and all is well.

Running systemctl status pure-ftpd, it tells me:

pure-ftpd.service: Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing.

I don't know what a oneshot service is. The documentation doesn't say when to use which, only "it is expected that the process has to exit before systemd starts follow-up units". I don't want systemd to wait for pure-ftpd to exit before starting other "units" (other services?) so that's not an option.

Grepping for pure (grep -r pure) in both /etc/systemd and /usr/lib/systemd gives only the result that I made myself: /etc/systemd/system/pure-ftpd.service.d/override.conf. There does not appear to be a service file, yet it complains about a doubly defined ExecStart option.

Calling /etc/init.d/pure-ftpd directly does not work either. Tracing that shell script, I see systemd hooked into this and hijacks it.

I also ran strace systemd restart pure-ftpd. Scrolling through, this catches my eye:

socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/run/systemd/private"}, 22) = 0
sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\0AUTH EXTERNAL ", iov_len=15}, {iov_base="30", iov_len=2}, {iov_base="\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n", iov_len=28}], msg_iovlen=3, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 45
sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l\1\4\1$\0\0\0\1\0\0\0\240\0\0\0\1\1o\0\31\0\0\0/org/fre"..., iov_len=176}, {iov_base="\21\0\0\0pure-ftpd.service\0\0\0\7\0\0\0repl"..., iov_len=36}], msg_iovlen=2, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 212
                 ---------------------->---------------------->---------------------->---------------------->---------------------->--------------------------^^^

So it sends something about "\21\0\0\0pure-ftpd.service\0\0\0\7\0\0\0repl"... over a unix socket. And evidently, systemd gets what it's talking about. It appears to me as if there is a template service file which is used by default if the real one is absent.

Attaching strace to the owner of /run/systemd/private (unsurprisingly: PID 1 / init), I see the authentication and the freedesktop message coming in, after which it immediately replies with an error message about the service not being properly loaded. It never checks for the existence of any files nor does it read from any.


Workarounds

  • I can systemctl disable pure-ftpd and edit the init.d file so it doesn't hook into systemd. But that's just an ugly hack. There should be a better way.
  • After typing all this, I found another answer describing that you can -- after all! -- do it via a config file and start pure-ftpd-wrapper (which is the default in the init.d script, but who knows whether systemd uses that). However, now I want to know the answer to the actual question:

Question

How do I provide additional command line options?

1

Did you know that systemd comes with some generators that generate the pure-ftpd.service file for you? The result is a not so nice unit file, but working.

The folder where it is generated is /run/systemd/generator.late You can see the source with cat pure-ftpd.service

Then, create a new /lib/systemd/system/pure-ftpd.service and put the contents of the /run/ unit in there (then you will be able to tune in the code of the unit).

Take in consideration that init.d is no longer used by debian (while using systemd) and all the non serviced services are generated automatically with the generators.

More info:

https://www.freedesktop.org/software/systemd/man/systemd.generator.html https://www.freedesktop.org/software/systemd/man/systemd-sysv-generator.html

systemd-sysv-generator is a generator that creates wrapper .service units for SysV init scripts in /etc/init.d/* at boot and when configuration of the system manager is reloaded. This will allow systemd(1) to support them similarly to native units.

  • If I understand your answer correctly, I can just add a regular service file with the same name to prevent systemd from wrapping the init.d file? – Luc Mar 1 at 10:27
  • @Luc that's it, as the documentation says: Regarding overriding semantics: there are two rules we try to follow when thinking about the overriding semantics: User configuration should override vendor configuration. This (mostly) means that stuff from /etc should override stuff from /usr. Native configuration should override non-native configuration. This (mostly) means that stuff you generate should never override native unit files for the same purpose. – Marc Palau Mar 4 at 8:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.