systemctl Exec format error when trying to run service - linux

Currently I wanted to run my dedicated server on my vps. When I run system systemctl start csgo.service it gives me error Load: error (Reason: Exec format error) when I run systemctl status csgo.service it gives me /lib/systemd/system/csgo.service:12: Executable path is not absolute: killall -TERM srcds_linux. Below are the service file that I am trying to run, am I making any mistake since it says format error?
[Unit]
Description=CSGO Server
[Service]
Type=simple
User=steam
Group=steam
Restart=on-failure
RestartSec=5
StartLimitInterval=60s
StartLimitBurst=3
ExecStart=/home/steam/steamcmd/csgo/srcds_run -game csgo -console -usercon +game_type 0 +game_mode 1 -tickrate 128 +mapgroup mg_active +map de_dust2 +sv_setsteamaccount GsltKeyHere -net_port_try 1
ExecStop=killall -TERM srcds_linux
[Install]
WantedBy=multi-user.target
My dedicated server files are inside /home/steam/steamcmd/csgo

Quoting the manual on unit files:
Note that shell command lines are not directly supported. If shell command lines are to be used, they need to be passed explicitly to a shell implementation of some kind.
Example: ExecStart=sh -c 'dmesg | tac'
You'll need to either use sh like that or figure out the actual path to your killall executable, e.g.
[Unit]
ExecStop=sh -c 'killall -TERM srcds_linux'
or
[Unit]
ExecStop=/sbin/killall -TERM srcds_linux
As an aside, that's not the best of ExecStop commands; it'll ruthlessly kill all srcds_linux executables, no matter if they're related to this service or not. Having no ExecStop command will have systemd terminate the service by itself:
Note that it is usually not sufficient to specify a command for this setting that only asks the service to terminate (for example, by queuing some form of termination signal for it), but does not wait for it to do so. Since the remaining processes of the services are killed according to KillMode= and KillSignal= as described above immediately after the command exited, this may not result in a clean stop. The specified command should hence be a synchronous operation, not an asynchronous one.

Related

How to send `SIGINT` over `systemctl` to custom daemon/service

I have a script that I would like to run as service on my Linux machine, let's call it my_script.sh. It is executable and can be run over ./path/to/my_scrit.sh.
I also have script that kills my_script.sh, let's call it kill_my_scprit.sh. The contents of kill_my_script.sh are:
#!/bin/bash
sudo kill -SIGINT $(pgrep my_script)
In essence, this should mimic Ctrl+C for my_script.sh.
This works perfectly fine if I run the scripts from a terminal, i.e. in ttyX I run ./path/to/my_scrit.sh to start it and in ttyY ./path/to/kill_my_scrit.sh to initiate the shut down sequence of my_script.sh.
As mentioned before, the goal is to run this as deamon, so I created /etc/systemd/system/my_script.service
[Unit]
....
[Service]
Type=simple
User=root
WorkingDirectory=/path/to/dir/
ExecStart=/path/to/my_script.sh
ExecStop=/path/to/kill_my_script.sh
Restart=on-failure
[Install]
...
Using sudo systemctl start my_script.service starts the script as expected, but using sudo systemctl stop my_script.service starts the shutdown sequence for my_script.sh, but doesn't let it finish... Am I missing something? The shutdown sequence takes roughly 10sec...

Linux systemd service file to start and stop a minecraft server

I am trying to run a minecraft server on a remote linux instance.
I would like the instance to start up the server on a screen named serverscreen which is owned by the user named minecraft once the system boots up, and run a stop command to the serverscreen when the instance shuts down. Then, it needs to wait untill the server has stopped before actually shutting down.
I am quite new to linux but I have managed to come up with a few commands that work, but I have issues trying to start and stop the server automatically.
I have tried quite a few things, like creating a .sh script to run on startup with crontab -e #reboot script.sh, or create a file in etc/rc.local with #!/bin/sh sh script.sh, but those methods didn't seem to work properly for me. Also, they do not run un shutdown unfortunately. Therefore, I thought it would be best to create a service file named minecraft.service with the following commands:
[Unit]
Description=Minecraft Server
After=network.target
[Service]
User=minecraft
Nice=5
KillMode=none
SuccessExitStatus=0 1
InaccessibleDirectories=/root /sys /srv /media -/lost+found
NoNewPrivileges=true
WorkingDirectory=/opt/minecraft/server
ReadWriteDirectories=/opt/minecraft/server
#### Command to start the server.
ExecStart=sudo -u minecraft screen -dmS serverscreen java -Xms6G -Xmx6G -jar /opt/minecraft/server/forgeserver.jar nogui
#### Command to stop the server.
ExecStop=sudo -u minecraft screen -S serverscreen -p 0 -X eval "stuff stop^M"
##### Try to wait untill the server has stopped. I am not sure about this line of code since I haven't been able to test it properly.
ExecStop=/bin/bash -c "while ps -p $MAINPID > /dev/null; do /bin/sleep 1; done"
[Install]
WantedBy=multi-user.target
but when running this, it gives me an error saying that I did not provide an absolute path for something.
Could someone help me setup a service file that will boot up the server on a screen named serverscreen for the user minecraft, and run command stop when the instance shuts down after the server has been stopped?
Thanks to #Riz, the service now works as intended by using a bash script in order to run the commands.

While loop in bash script breaks systemd service

I'm on Debian and I have a systemd service that calls a bash script.
The script contains an infinite while loop, as I need it to check something every X seconds infinitely.
The systemd service crashes once it hits the "while true; do" line.
The script runs fine if I execute it manually.
Why doesn't systemd like it? What do I do?
Here are the service and the script. As I've indicated, an echo statement before the "while true; do" prints. The echo statement after the "while true; do" line does not print.
/etc/systemd/system/stream.service:
[Service]
WorkingDirectory=/home/pi/
ExecStart=/home/pi/joi_main.sh
Restart=no
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=stream_service
User=pi
Group=pi
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
/home/pi/joi_main.sh:
#!/bin/bash -e
today=`/bin/date '+%Y_%m_%d__%H_%M_%S'`
exec 2> "/home/pi/stream_logs/$today.$RANDOM.log"
exec 1>&2
#Wait 120s for system to finish booting
sleep 120
#Initial config
export AUDIODEV=mic_mono
export AUDIODRIVER=alsa
sudo sysctl fs.pipe-max-size=1048576
echo "This line prints"
# Check if video buffer is full every minute. if full, the stream needs to restart
while true; do
echo "This line doesn't"
if grep "100% full" /home/pi/video_buffer_usage.txt; then
echo "Buffer is full!"
# Kill existing processes
pkill -f “raspivid|rec|buffer|ffmpeg”
# Wait 10s
sleep 10
./joi_stream.sh &
fi
sleep 60
done
Journalctl seems completely unhelpful, but here it is. No errors. Why is "session closed"?
Mar 31 02:13:41 raspberrypi sudo[1369]: pi : TTY=unknown ; PWD=/home/pi ; USER=root ; COMMAND=/sbin/sysctl fs.pipe-max-size=1048576
Mar 31 02:13:41 raspberrypi sudo[1369]: pam_unix(sudo:session): session opened for user root by (uid=0)
Mar 31 02:13:41 raspberrypi sudo[1369]: pam_unix(sudo:session): session closed for user root
(Please don't tell me to start yet another systemd service for just this while loop. I want it to be part of this main script because it needs to run after everything else, and if I turn off the main service I don't want the while loop running either, so maintaining two systemd services would only add troube.)
The contents of ./joi_stream.sh were not shared, but here's a problem I see with your systemd solution. It doesn't directly explain your behavior, but may be related:
In your systemd configuration, you redirect both STDOUT and STDERR to syslog, but in your script, you redirect STDERR (file descriptor "2") to a file, and redirect STDOUT (file descriptor "1') to STDERR.
exec 2> "/home/pi/stream_logs/$today.$RANDOM.log"
exec 1>&2
If your ./joi_stream.sh expected your redirection of these file descriptors to another file to work, it may not. If the file is just for logging, I would get rid of these lines and let the systemd journal handle that-- it will tag the logs with your unit you can review your logs specifically:
journalctl -u your-unit-name.service
Also, in systemd, you wouldn't normally put in a sleep to wait until the systemd has booted. Instead, you would use a .timer unit.
The .timer file would instruct to run the main logic every minute, so the "while" loop would not be required. The timer unit would contain directives like:
# Run for the first time 2 minutes after boot
# and every minute after that
OnBootSec=120
OnUnitActiveSec=60
It would be timer unit which is enabled to start on boot. Timer files can be super-simple. Just create a .timer file in /etc/systemd/system and give it the same name as the service file you want it to activate:
[Unit]
Description=Runs my service every minute
[Timer]
# Run for the first time 2 minutes after boot
# and every minute after that
OnBootSec=120
OnUnitActiveSec=60
[Install]
WantedBy=timers.target
To start and test your timer immediately, run:
sudo systemctl start my-service.timer
You can review the status of timers with:
sudo systemctl list-timers
The systemd solution is more robust than the rc.local solution. If your rc.local solution dies for any reason, it will not restart. However, if your script dies will run under systemd, the timer will still run it again a minute later.
FYI, everything works if I call /home/pi/joi_main.sh from /etc/rc.local instead of using a systemd service. I'll use rc.local and kill the service.

Prevent stop auditd service in Redhat 7

Curently, i want auditd service run forever and user can not stop this via any commands.
Current my auditd service:
~]# systemctl cat auditd
# /usr/lib/systemd/system/auditd.service
[Unit]
Description=Security Auditing Service
DefaultDependencies=no
After=local-fs.target systemd-tmpfiles-setup.service
Conflicts=shutdown.target
Before=sysinit.target shutdown.target
RefuseManualStop=yes
ConditionKernelCommandLine=!audit=0
[Service]
ExecStart=/sbin/auditd -n
## To not use augenrules, copy this file to /etc/systemd/system/auditd.service
## and comment/delete the next line and uncomment the auditctl line.
## NOTE: augenrules expect any rules to be added to /etc/audit/rules.d/
ExecStartPost=-/sbin/augenrules --load
#ExecStartPost=-/sbin/auditctl -R /etc/audit/audit.rules
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/auditd.service.d/override.conf
[Service]
ExecReload=
ExecReload=/bin/kill -HUP $MAINPID ; /sbin/augenrules --load
I can't stop this service from command:
# systemctl stop auditd.service
Failed to stop auditd.service: Operation refused, unit auditd.service may be requested by dependency only.
But when i using service auditd stop command. I can stop this service normally.
# service auditd stop
Stopping logging: [ OK ]
How can i prevent it? Thanks
The administrator (root) will always be able to manually kill the auditd process (which is what the service command does). What systemd is doing here is only to prevent the administrator from doing it via the systemctl interface.
In both cases, unprivileged users can not kill the daemon.
If you want to restrict even what root can do, you will have to use SELinux and customize the policy.
Some actions of service command are not redirected to systemctl but run some specific scripts located in /usr/libexec/initscripts/legacy-actions.
In this case, stop command will call this script:
/usr/libexec/initscripts/legacy-actions/auditd/stop
If you want that, the audited service can't be stopped by service command, you can remove this script, the action "stop" will be redirected to systemctl, which will block it b/c of the parameter "RefuseManualStop=yes".
But this doesn't mean that you can't kill the process of course.

Script not starting on boot with start-stop-daemon

My script (located in /etc/init.d) is creating a pid file ($PIDFILE), but there is no process running. My daemon script includes:
start-stop-daemon --start --quiet --pidfile $PIDFILE -m -b --startas $DAEMON --test > /dev/null || return 1
The script works fine when executing it manually.
You need to create startup links.
sudo update-rc.d SCRIPT_NAME defaults
then reboot. SCRIPT_NAME is the name of the script in /etc/init.d (Without the path)
Was able to get it working, but tried so many things, don't know exactly what fixed it (probably an error in script or config). However, learned a lot and wanted to share since I can't find much of the same in the internet abyss.
It seems Ubuntu (and many other distros based on Ubuntu, including Mint) has migrated to Upstart for job and service management. Upstart includes SysVinit (using /etc/init.d daemons) compatibility that still can use update-rc.d to manage daemons (so if you are familiar with that usage, you can keep on using it). The Upstart method is to use a single .conf file in the /etc/init folder. My SCRIPT.conf file is very simple (I'm using a python script):
start on filesystem or runlevel [2345]
stop on runlevel [016]
exec python /usr/share/python-support/SCRIPT/SCRIPT.py
This simple file completely replaces the standard script in /etc/init.d with the case statement to provide [start|stop|restart|reload] functions and the pointer to /usr/bin/SCRIPT. You can see that it includes runlevel control that would normally be found in the /etc/rc*.d files (thus eliminating several files).
I tried update-rc.d to create the necessary /etc/rc*.d/ files for my daemon. My daemon bash script is located in /etc/init.d and includes the start-stop-daemon command as in my original question. (That command also works fine from terminal.)
I had /etc/rc*.d/ files, the bash script in /etc/init.d and /etc/init/SCRIPT.conf file during boot and it seems that Upstart likely first looks for the .conf file for its direction because the SysVinit command service SCRIPT [start|stop|restart|reload] returns Unknown Instance, however you can find the process is running with ps -elf | grep SCRIPT_FILE.
One interesting thing to note is the forking of your daemon when using .conf. The script as written above only spawns one fork of the daemon. However, total independence of the original script is possible by using expect fork or expect daemon and respawn (see the Upstart Cookbook for reference). Using these will ensure that your daemon will never be killed (at least by using the kill command).
I continued to test both my daemon and the boot process by utilizing the sudo initctl reload-configuration command. This reloads the conf files where you can test your daemon by the sudo [start|stop|restart] SCRIPT command. The result of the start command is:
$ sudo start SCRIPT
SCRIPT start/running, process xxxx
$ sudo restart SCRIPT
SCRIPT start/running, process xxxx
$ sudo stop SCRIPT
SCRIPT stop/waiting
Also, there is a nice log in /var/log/upstart/SCRIPT.log that gives you useful information for your daemon during boot. Mine still has a very annoying bug that prevents root from displaying osd messages with notify-send from my daemon. My log file includes a gtk warning (I will open another question to solicit help).
Hope this helps others in developing their daemons.

Resources