What is the difference between systemd's 'oneshot' and 'simple' service types?
The Type=oneshot
service unit:
blocks on a start operation until the first process exits, and its state will be reported as "activating";
once the first process exits, transitions from "activating" straight to "inactive", unless
RemainAfterExit=true
is set (in which case it becomes "active" with no processes!);may have any number (0 or more) of
ExecStart=
directives which will be executed sequentially (waiting for each started process to exit before starting the next one);may leave out
ExecStart=
but haveExecStop=
(useful together withRemainAfterExit=true
for arranging things to run on system shutdown).
The Type=simple
service unit:
does not block on a start operation (i. e. becomes "active" immediately after forking off the first process, even if it is still initializing!);
once the first process exits, transitions from "active" to "inactive" (there is no
RemainAfterExit=
option);is generally discouraged because there is no way to distinguish situations like "exited on start because of a configuration error" from "crashed after 500ms of runtime" and suchlike.
Both Type=oneshot
and Type=simple
units:
- ignore any children of the first process, so do not use these modes with forking processes (note: you may use
Type=oneshot
withKillMode=none
, but only do this if you know what you are doing).
which systemd TYPE of service to use at machine start i some code has to stay forever
Do not use nohup
. Do not use &
. Do not wrap your script in another script. Doing either of these first two things stops systemd from detecting when your program crashed and restarting it, and the third complicates signal handling.
Do use Restart=always
. Do create an Install
section, and configure your service to be a dependency of a target that is started on boot.
[Unit]
Description=R4 start
[Service]
WorkingDirectory=/home/pi/tools
ExecStart=/home/pi/tools/run-poll-loop
Restart=always
[Install]
WantedBy=multi-user.target
...where run-poll-loop
is executable (chmod +x
) and contains your logic (note, command names should not have extensions; .sh
is bad practice):
#!/usr/bin/env bash
while :; do
# ...do whatever you need here...
sleep 5
done
Note that for a slower delay than every-5-seconds, I would suggest a systemd timer running a oneshot service that only does a single iteration of the loop each time; but for this short a timer, that would add up to quite a bit of process-startup overhead.
ExecStart bash script fails; However, running it manually works
So, after playing around with virtualenv
I finally made it work! Previously, when running ./vmx.sh script, it would require the system to use Python2.7; however, every time my host would reboot, if I wanted to fully automate the boot of all of my VMs, I would require to change the PATH of Python by running manually the following command onto my terminal:
echo 'export PATH=/opt/rh/python27/root/usr/bin:$PATH' >> /etc/profile
PATH=/opt/rh/python27/root/usr/bin:$PATH
export PATH
cd /opt/rh/python27/ && . enable && pip install netifaces pyyaml
Instead of running the previous commands from a .sh script, which ended up not working for me, It was pointed out that "Python-related path tweaks, will not be available for the subsequent ExecStart commands". For that reason, I did the following:
- Instead of running scl enable python27 bash (which would make as default my Python Version until you logout), I decided to keep the changes by creating a script under /etc/profile.d/
#!/bin/bash
source scl_source enable python27
I installed virtualenv
pip install virtualenv
Created a virtual environment
virtualenv --python=/usr/bin/python2.7 vMX-ENV
which I would use to install all my packages and scripts to install my VMsActivated my Virtual Environment
source /home/vMX-ENV/bin/activate
Created a Directory (vMX-*) where ./vmx.sh script will be located.
# ls
bin lib lib64 pyvenv.cfg vMX-21.1R1
- Inside of that Directory, I created a bash script that will be initiated by the service when on boot, I called it: pyrun.sh, this script runs the ./vmx.sh script "Credit: AKX"
#!/bin/bash
source /home/vMX-ENV/bin/activate
./vmx.sh -lv --start --cfg config/pod17/vmx1.conf
# ...
- Created the vmxd.service and
ExecStart=/bin/bash -c './pyrun.sh'
By creating a virtualenv I was able to isolate my Python project by only creating a unique environment with all the needed packages and running only Python2.7 which is required to run ./vmx.sh
After rebooting the host, here is the journalctl -u vmxd.service
successful output as a result:
Starting Juniper vMX Router...
==================================================
Welcome to VMX
==================================================
[...]
Execute multiple commands with && in systemd service ExecStart on RedHat 7.9
The command line is not given to a shell, so &&
is not valid. You would need, for example,
ExecStart=/bin/bash -c 'sleep 45 && /bin/bash bin/eum.sh start'
or you could separate the commands into
ExecStartPre=/usr/bin/sleep 45
ExecStart=/bin/bash bin/eum.sh start
Related Topics
How to Boot the Linux Kernel Without Creating an Initrd Image
How Are Percpu Pointers Implemented in the Linux Kernel
Pause Programmatically Video Player Mpv
When Should Xargs Be Preferred Over While-Read Loops
Bash And/Or .Bashrc Not Working Properly After Su or Ssh Login Unless Run "Bash" Command
Why Can't We Use C Standard Library Functions in Kernel Development
Determine Tsc Frequency on Linux
How to Remove Warning About Storing Unencrypted Password After Committing File in Svn
How to Get Eclipse Swt Browser Component Running on Ubuntu 11.04 (Natty Narwhal) with Webkit
How to Get Notified for Ip Address Changes Automatically
Bash Script to Get All Ip Addresses
Debugging in Pycharm with Sudo Privileges
How to Stop 'Uninterruptible' Process on Linux
File Size in Human Readable Format
Creating a Raw Printer Queue in Cups (Host) and Adding Them Through Cups (Client)
Lowest Latency Notification Method Between Process Under Linux