Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I need to run systemd-tmpfiles --create during the boot process with a systemd distro. So I need to create a systemd .service file doing this job.

In this question you can read all the details about what I need and why: How does systemd-tmpfiles work?

I have read some docs about it and I am writing the following test:

[Unit]
Description=Execute tmpfiles to disable usb-wakeup # see details in the link above
Requires=multi-user.target # see details in the link above
After=multi-user.target    # see details in the link above

[Service]
Type=oneshot
ExecStart=/usr/bin/systemd-tmpfiles --create

[Install]
WantedBy=multi-user.target

But I'm not sure, because systemd-tmpfiles is not a simple program but a piece of systemd itself. I wouldn't like to break my system.

Any tips about a correct .service file?

share|improve this question
    
Check the copious documentation on systemd at freedesktop.org/wiki/Software/systemd. You can override the system's defaults by your own files. –  vonbrand Jan 21 '13 at 20:32
add comment

2 Answers

up vote 4 down vote accepted

[This does not directly address the issue of systemd-tmpfiles but I think you have already recognized that in this particular case you are better off just using echo.]

First up, "multi-user.target" may or may not be what you want to use. If you are familiar with the concept of runlevels from SysV style init stuff, multi-user is the systemd equivalent of runlevel 3, which is a multi-user system that boots to a console, not a GUI. The equivalent of runlevel 5, which boots to X, is graphical.target. The default is determined by a symlink in /etc/systemd/system called default.target, use ls to find where it points:

»ls -l /etc/systemd/system/default.target
default.target -> /usr/lib/systemd/system/multi-user.target

For normal linux desktops this will be graphical.target. This is actually not important if you want the boot service you are creating to start regardless of what the default runlevel/target is -- in that case, we can just use default.target, and not worry what it is an alias for. If you use multi-user, however, and your default is graphical, your service won't happen.

Depending on the service, there may be more appropriate and specific targets or services that you want to start this one in relation to. Based on your other question, default.target is probably fine. As a note, the difference between a "target" and a "service" is that a service contains a [Service] section which actually runs a process; a target is just a way of grouping services together via the various "depends" and "requires" directives; it doesn't do anything of its own beyond triggering other targets or services.

When a service starts is determined by what other services explicitly depend on it. In the case of a simple, stand-alone event like this that we want run late in the boot process, we can use this combination of directives:

[Unit]
After=default.target

[Install]
WantedBy=default.target

The "Install" section is used when the service is installed; "WantedBy" specifies a target we want this service to be included with (meaning it will run if that target does, but nb. this does not determine when it will run in relation to others). Since we actually want this service to run later rather than sooner, we then specify an "After" clause. This does not actually need to be the same as the WantedBy target (it usually isn't) and can be completely omitted if you don't care when it happens; I'm just using it on the hunch that most other stuff will be run in relation to stuff that is somewhere chained to something that has specified Before=default.target (which we could also have used; a target's wants are appraised before the target is run).

For the example, I'll just echo "hello world" to the console. The service itself is described in the [Service] section:

[Service]
Type=forking
ExecStart=/usr/local/bin/helloworld

The command needs a full path. The reason I did not just use /usr/bin/echo "hello world" is that it won't work (the output goes to /dev/null, I think), and while a service that does an echo "hello world" > /dev/console will, experimentation demonstrates that using shell redirection in an ExecStart directive won't. So /usr/local/bin/helloworld is a shell script with that one line, echo "hello world" > /dev/console.

Note the Type=forking, which is necessary for a shell script.

Our complete, minimal service file is just those three sections ([Unit], [Service], and [Install]). To install, place the file or a symlink to it in either /etc/systemd/system or /usr/lib/systemd/system, and:

systemctl --system enable helloworld

It should print ln -s .... This does not run the service, it just configures it to run at boot as discussed above.

That's it in a nutshell. man systemd.unit and man systemd.service have more details.

share|improve this answer
    
Thank you, very useful answer and problem solved. Just a note, in my distro (Chakra Linux) default.target is not in /etc/systemd/system, but it's only in /usr/lib/systemd/system –  ital Jan 18 '13 at 22:37
    
Output from commands gets logged (where else could it go)? –  vonbrand Jan 21 '13 at 20:33
    
The /usr/lib/systemd/... files are fallback (default), you are supposed to drop yours in /etc/systemd/... –  vonbrand Jan 21 '13 at 20:34
add comment

For the systemd-tmpfiles service: it should ship with your distribution, but you can always get the service file from the upstream git-repository

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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