Converting watch into a unit file systemd - linux

I've got a shell script as follows
ss.sh
#!/bin/bash
opFile="custom.data"
sourceFile="TestOutput"
./fc app test > $sourceFile
grep -oP '[0-9.]+(?=%)|[0-9.]+(?=[A-Z]+ of)' "$sourceFile" | tr '\n' ',' > $opFile
sed -i 's/,$//' $opFile
The requirement is that I need to use this script with the watch command. And I'd like to make this into a systemctl service. I did it as so.
sc.sh
#!/bin/bash
watch -n 60 /root/ss.sh
And in my /etc/systemd/system,
log_info.service
[Unit]
Description="Test Desc"
After=network.target
[Service]
ExecStart=/root/sc.sh
Type=simple
[Install]
WantedBy=default.target
When I run systemctl start log_info.service, It runs but not continuously the way I'd like it to.
On running sytemctl status log_info.service,
info_log.service - "Test Desc"
Loaded: loaded (/etc/systemd/system/info_log.service; disabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Mon 2016-09-12 08:17:02 UTC; 2min 18s ago
Process: 35555 ExecStart=/root/sc.sh (code=exited, status=1/FAILURE)
Main PID: 35555 (code=exited, status=1/FAILURE)
Sep 12 08:17:02 mo-b428aa6b4 systemd[1]: Started "Test Desc".
Sep 12 08:17:02 mo-b428aa6b4 sc.sh[35654]: Error opening terminal: unknown.
Sep 12 08:17:02 mo-b428aa6b4 systemd[1]: info_log.service: Main process exited, code=exited, status=1/FAILURE
Sep 12 08:17:02 mo-b428aa6b4 systemd[1]: info_log.service: Unit entered failed state.
Sep 12 08:17:02 mo-b428aa6b4 systemd[1]: info_log.service: Failed with result 'exit-code'.
Any ideas as to why it's not running right? Any help would be appreciated!

So the reason I learnt (from superuser) for this failing was exactly what was in my error console, i.e,
Error opening terminal: unknown
Watch can only be executed from the terminal because it requires access to a terminal, while services don't have that access.
A possible alternative to watch could be using a command that doesn't require the terminal, like screen or tmux. Or, another alternative which worked for me, that was suggested by grawity on superuser, was
# foo.timer
[Unit]
Description=Do whatever
[Timer]
OnActiveSec=60
OnUnitActiveSec=60
[Install]
WantedBy=timers.target
The logic behind this was that, the need was to run the script every 60 seconds, not to use watch. Hence, grawity suggested that I use a timer unit file that calls the service file every 60 seconds instead. If the service unit was a different name from the timer unit, [Timer] Unit= can be used.
Hope this helped you and +1 to grawity and Eric Renouf from superuser for the answers!

Related

systemd: tar (backup) issue backup.service

The following should make a tar file with the date and after making the .tar.gz file, check wheather there is a file older than 30 days, if yes, remove it.
Here is what I get when executing it in systemd. it works flawlessly when directly entered to the commandline:
executing: journalctl -u backup.service
Jun 12 14:42:39 Debian-84-jessie-64-LAMP systemd[1]: Starting Backing up folders (/var/www/)...
Jun 12 14:42:39 Debian-84-jessie-64-LAMP systemd[1]: Started Backing up folders (/var/www/).
Jun 12 14:42:39 Debian-84-jessie-64-LAMP tar[27620]: /bin/tar: Von den Optionen „-Acdtrux“, „--delete“ oder „--test-label“ ist j
Jun 12 14:42:39 Debian-84-jessie-64-LAMP tar[27620]: „/bin/tar --help“ oder „/bin/tar --usage“ gibt weitere Informationen.
Jun 12 14:42:39 Debian-84-jessie-64-LAMP systemd[1]: backup.service: main process exited, code=exited, status=2/INVALIDARGUMENT
Jun 12 14:42:39 Debian-84-jessie-64-LAMP systemd[1]: Unit backup.service entered failed state.
backup.service
[Unit]
Description=Backing up folders (/var/www/)
[Service]
WorkingDirectory=/backup/www/
ExecStart=/bin/tar -czpf "backup_$(date '+%y-%m-%d').tar.gz" /var/www/ && find /backup/www/ -maxdepth 0 -name "backup_*.*" -mtime +30
backup.timer
[Unit]
Description=Make Backup of /var/www/
[Timer]
OnCalendar=weekly
Persistent=true
[Install]
WantedBy=timers.target
You've asked a variation of the FAQ Why do things behave differently under systemd?.
In that answer to that FAQ, you'll notice that system has a much more restrictive command line syntax, as documented in COMMAND LINES in man systemd.service.
Keep in mind you can have multiple ExecStart= lines, so you don't need to use the && syntax, you can just add an extra ExecStart= line.
Your text says your command would remove files older than 30 days, but it does not attempt to do this. In you what you posted, the find command is run, but no remove command.
This is how I solved it in my backup.service file:
[Unit]
Description=Backing up folders (/var/www/)
[Service]
Type=oneshot
WorkingDirectory=/backup/www/
ExecStart=/bin/tar -zcf "backup_weekly.tar.gz" /var/www
ExecStart=/usr/bin/find /backup/www/ -maxdepth 0 -name "backup_*.tar.gz" -type f -mtime +30 -delete
ExecStart=/bin/sh /backup/www/rename_backup.sh
This is my backup.timer file:
[Unit]
Description=Make Backup of /var/www/
[Timer]
OnCalendar=weekly
Persistent=true
[Install]
WantedBy=timers.target
And lastly here is the script file called rename_backup.sh which is located in the backup folder:
mv /backup/www/backup_weekly.tar.gz /backup/www/backup_weekly_$(date +%F).tar.gz
The reason for not opting to just execute a script was, that I wanted to purely run it from systemd, having to copy only two files, and making it system independent. Turns out that systemd has it's own preferences and issues with bash commands, making some of them not work.
Next to my execution, the script makes the backup, naming it "backup_weekly.tar.gz", no date yet. However then the script is called, which renames the "backup_weekly.tar.gz" (which always will be created with that name by systemd.service) to "backup_weekly_DATE.tar.gz". I assume this is not the most elegant way, but it seems to be ok, since this is quite a short script. I think it would be safe to say, that copying this to another system should do no harm, even if it turns out to fail for some reason.

Process (re)starting a Docker container from systemd exits unexpectedly

I have a docker container.During the restart of the linux server docker container is stopped so in systemd, script file is added for the container restart.This script is also stopping the chef-client. But script is executing only half of the commands.I don't know why it is stopping after chef-client stop.After that it is not proceeding.
Restart script:
[root#server01 user1]# more /apps/service-scripts/docker-container-restart.sh
#!/bin/bash
echo "Starting to stop the chef-client automatic running.."
service chef-client stop
echo "Completed the stopping the chef-client automatic running"
echo "Restart check... the Applicaiton Container $(date)"
IsAppRunning=$(docker inspect -f '{{.State.Running}}' app-prod)
echo "IsAppRunning state $IsAppRunning"
if [ "$IsAppRunning" != "true" ]; then
IsAppRunning=$(docker inspect -f '{{.State.Running}}' app-prod)
echo "Restarting.... the Applicaiton Container $(date)"
docker restart app-prod
IsAppRunning=$(docker inspect -f '{{.State.Running}}' app-prod)
echo "Restart completed($IsAppRunning) the Applicaiton Container $(date)"
else
echo "Restart is not required, app is already up and running"
fi
Systemctl log:
[root#server01 user1] systemctl status app-docker-container.service
● app-docker-container.service - Application start
Loaded: loaded (/etc/systemd/system/app-docker-container.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2017-09-24 16:00:40 CDT; 18h ago
Main PID: 1187 (docker-container-restart)
Memory: 16.4M
CGroup: /system.slice/app-docker-container.service
├─1187 /bin/bash /apps/service-scripts/docker-container-restart.sh
└─1220 docker inspect -f {{.State.Running}} app-prod
Sep 24 16:00:40 server01 systemd[1]: Started Application start.
Sep 24 16:00:40 server01 systemd[1]: Starting Application start...
Sep 24 16:00:40 server01 docker-container-restart.sh[1187]: Starting to stop the chef-client automatic running..
Sep 24 16:00:41 server01 docker-container-restart.sh[1187]: Redirecting to /bin/systemctl stop chef-client.service
Sep 24 16:00:41 server01 docker-container-restart.sh[1187]: Completed the stopping the chef-client automatic running
Sep 24 16:00:41 server01 docker-container-restart.sh[1187]: Restart check... the Applicaiton Container Sun Sep 24 16:00:41 CDT 2017
SystemD:
[root#server01 user1]# more /etc/systemd/system/app-docker-container.service
[Unit]
Description=Application start
After=docker.service,chef-client.service
[Service]
Type=simple
ExecStart=/apps/service-scripts/docker-container-restart.sh
[Install]
WantedBy=multi-user.target

Why does systemd keep killing my service

I would like to start an interactive script from systemd after the getty.target has been reached. This works so far, however, systemd kills the script after a couple of seconds. The systemd unit looks like the following:
[Unit]
Description = Some interactive script
Requires = getty#tty1.service
After = getty#tty1.service
[Service]
Type = oneshot
ExecStart = /usr/local/bin/my-script
StandardInput = tty
StandardOutput = tty
TTYPath = /dev/tty1
TTYReset = yes
TTYVHangup = yes
[Install]
WantedBy = multi-user.target
Within the script there are calls to dialog, mount etc. Nothing very special but it is an interactive script. Systemd keeps killing the script and I don't understand why. The output of systemctl status interactive-script.service looks like:
● interactive-script.service - Some interactive script
Loaded: loaded (/etc/systemd/system/interactive-script.service; enabled)
Active: inactive (dead) since Tue 2016-06-28 10:18:07 UTC; 14min ago
Main PID: 364 (code=killed, signal=HUP)
And the log output gotten with journalctl -b -u interactive-script.service is empty:
-- Logs begin at Mon 2015-11-09 11:49:52 UTC, end at Tue 2016-06-28 10:30:28 UTC. --
I already tried to add KillMode=none, no luck. Then I tried TimeoutStartSec=infinity - systemd complains that it doesn't understand it therefore I tried to set it to 10000 but the script gets killed after just some seconds. I tried to run it as Type=simple and Type=forking, all to no avail.
The point is that starting the script seems to work fine (the dialogs appear) but systemd keeps killing the script. How can I achieve that systemd does not kill this interactive script?

Systemd - detect in ExecStopPost whether service exited without error

I have an application that after it's finished and exited normally should not be restarted. After this app has done its business I'd like to shutdown the instance (ec2). I was thinking of doing this using systemd unit files with the options
Restart=on-failure
ExecStopPost=/path/to/script.sh
The script that should run on ExecStopPost:
#!/usr/bin/env bash
# sleep 1; adding sleep didn't help
# this always comes out deactivating
service_status=$(systemctl is-failed app-importer)
# could also do the other way round and check for failed
if [ $service_status = "inactive" ]
then
echo "Service exited normally: $service_status . Shutting down..."
#shutdown -t 5
else
echo "Service did not exit normally - $service_status"
fi
exit 0
The problem is that when post stop runs I can't seem to detect whether the service ended normally or not, the status then is deactivating, only after do I know if it enters a failed state or not.
Your problem is that systemd considers the service to be deactivating until the ExecPostStop process finishes. Putting sleeps in doesn't help since it's just going to wait longer. The idea for an ExecPostStop was to clean up anything the service might leave behind, like temp files, UNIX sockets, etc. The service is not done, and ready to start again, until the cleanup is finished. So what systemd is doing does make sense if you look at it that way.
What you should do is check $SERVICE_RESULT, $EXIT_CODE and/or $EXIT_STATUS in your script, which will tell you how the service stopped. Example:
#!/bin/sh
echo running exec post script | logger
systemctl is-failed foobar.service | logger
echo $SERVICE_RESULT, $EXIT_CODE and $EXIT_STATUS | logger
When service is allowed to to run to completion:
Sep 17 05:58:14 systemd[1]: Started foobar.
Sep 17 05:58:17 root[1663]: foobar service will now exit
Sep 17 05:58:17 root[1669]: running exec post script
Sep 17 05:58:17 root[1671]: deactivating
Sep 17 05:58:17 root[1673]: success, exited and 0
And when the service is stopped before it finishes:
Sep 17 05:57:22 systemd[1]: Started foobar.
Sep 17 05:57:24 systemd[1]: Stopping foobar...
Sep 17 05:57:24 root[1643]: running exec post script
Sep 17 05:57:24 root[1645]: deactivating
Sep 17 05:57:24 root[1647]: success, killed and TERM
Sep 17 05:57:24 systemd[1]: Stopped foobar.

Redirect systemd script output to console

How can I redirect output of script which is run by systemd ExecStart script to boot console?
I need to debug what is wrong with script until boot but I can't use journalctl because it's embedded linux with ROM rootfs.
Now my .service file looks like:
[Unit]
Description=Init script
After=network.target
Before=getty#tty1.service
[Service]
Type=oneshot
ExecStart=/usr/lib/systemd/test_init_script
ExecStartPre=/usr/bin/echo -e \033%G
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/
Enviroment=TERM=xterm
[Install]
WantedBy=multi-user.target
test_init_script:
#!/bin/sh -
echo "Test!"
And it didn't work, after boot I receive message:
#systemctl status test_init_script.service
test_init_script.service - Init script
Loaded: loaded (/usr/lib/systemd/test_init_script.service)
Active: failed (Result: exit-code) Since Thu 1970-01-01 08:26:03 CST; 19s ago
Process: 170 ExecStartOre=/usr/bin/echo -e -G (code=exited, status=203/EXEC)
Did anyone know how to redirect script output to terminal?
Ok, so I resolve this problem by building image with changed file:
/etc/journald.conf
Where I change storage option to volatile:
Storage=volatile
This option means that all journald data will be store in RAM so this is a workaround for read only file system.
Please refer to journald manual page to see more options.

Resources