How to write startup script for Systemd?
I have 2 graphics cards on my laptop. One is IGP and another discrete.
I’ve written a shell script to to turn off the discrete graphics card.
How can I convert it to systemd script to run it at start-up?
There are mainly two approaches to do that:
With script
If you have to run a script, you don’t convert it but rather run the script via a systemd
service:
Therefore you need two files: the script and the .service
file (unit configuration file).
Make sure your script is executable and the first line (the shebang) is #!/bin/sh
. Then create the .service
file in /etc/systemd/system
(a plain text file, let’s call it vgaoff.service
).
For example:
- the script:
/usr/bin/vgaoff
- the unit file:
/etc/systemd/system/vgaoff.service
Now, edit the unit file. Its content depends on how your script works:
If vgaoff
just powers off the gpu, e.g.:
exec blah-blah pwrOFF etc
then the content of vgaoff.service
should be:
[Unit]
Description=Power-off gpu
[Service]
Type=oneshot
ExecStart=/usr/bin/vgaoff
[Install]
WantedBy=multi-user.target
If vgaoff
is used to power off the GPU and also to power it back on, e.g.:
start() {
exec blah-blah pwrOFF etc
}
stop() {
exec blah-blah pwrON etc
}
case $1 in
start|stop) "$1" ;;
esac
then the content of vgaoff.service
should be:
[Unit]
Description=Power-off gpu
[Service]
Type=oneshot
ExecStart=/usr/bin/vgaoff start
ExecStop=/usr/bin/vgaoff stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Without script
For the most trivial cases, you can do without the script and execute a certain command directly:
To power off:
[Unit]
Description=Power-off gpu
[Service]
Type=oneshot
ExecStart=/bin/sh -c "echo OFF > /whatever/vga_pwr_gadget/switch"
[Install]
WantedBy=multi-user.target
To power off and on:
[Unit]
Description=Power-off gpu
[Service]
Type=oneshot
ExecStart=/bin/sh -c "echo OFF > /whatever/vga_pwr_gadget/switch"
ExecStop=/bin/sh -c "echo ON > /whatever/vga_pwr_gadget/switch"
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Enable the service
Once you’re done with the files, enable the service:
systemctl enable vgaoff.service
It will start automatically on next boot. You could even enable and start the service in one go with
systemctl enable --now vgaoff.service
as of systemd v.220
(on older setups you’ll have to start it manually).
For more details see systemd.service
manual page.
Troubleshooting
Adding startup items in systemd is complex and cumbersome. To make this more convenient, I have wirte a tool add_service which provides a simple way to quickly add startup item in systemd.
Install:
pip3 install add_service
Usage:
python -m add_service [shell_file/cmd] [user (default `whoami`)]
Examples:
python -m add_service ssh_nat.sh # by default user is `whoami`
python -m add_service "`which python3` -m http.server 80" root