Converting the watch command into a unit file systemd

2

1

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!

Izy-

Posted 2016-09-12T09:19:06.087

Reputation: 123

the key is Error opening terminal: unknown. watch needs to write to a terminal, but services do not have access to one. Why do you want this to be a service? – Eric Renouf – 2016-09-12T11:31:10.853

Ah. How interesting. Well, because running this script as a foreground one, causes that terminal session to become occupied. What else would you suggest? Background? – Izy- – 2016-09-12T12:19:33.000

If you don't want it to occupy the terminal, I'd recommend either not using watch or running something like screen or tmux so you can have one window running that and others that you are doing other work in. Bonus to this: you can reconnect to the same terminals if you login remotely and the things you're doing will survive an ssh disconnect – Eric Renouf – 2016-09-12T12:21:56.810

This is all being done remotely. Running of both scripts is all on a remote system. Which I don't really have permission to install third party applications on. And for ease of running, we wanted to make it a systemctl call. Any other ideas, sir? – Izy- – 2016-09-12T12:33:44.733

Are you sure screen and tmux are unavailable? They may be there already. Failing that, I'd probably either open 2 windows if I wanted to have that up all the time or just episodically run it. – Eric Renouf – 2016-09-12T12:36:48.607

Answers

3

As the error message shows, watch can be only used from a terminal:

Error opening terminal: unknown

But your requirement quite probably isn't to use the script with watch. Your requirement is to run it every 60 seconds, and watch is the tool you ended up choosing.

The most common method to run a script every 60 seconds would be cron – e.g. a * * * * * cronjob would be run every minute. With systemd .services you can use a .timer unit for the same purpose:

# foo.timer
[Unit]
Description=Do whatever

[Timer]
OnActiveSec=60
OnUnitActiveSec=60

[Install]
WantedBy=timers.target

Then instead of starting the .service, you start the .timer instead, and it periodically tries to start the .service on its own.

user1686

Posted 2016-09-12T09:19:06.087

Reputation: 283 655

Ah, I hadn't looked carefully enough at the script to see its only point was to modify a file, not display output (which I lept to). This is for sure the way forward then instead of faking it with the terminal like I had been discussing in comments. – Eric Renouf – 2016-09-12T14:00:36.110

Thank you both for your help. Regarding this solution, could you please run me through the procedure again, I'm new to systemd services. This foo.timer file you've created, it's to run every 60 seconds. But is it still a unit file for systemd? Where does this file call my ss.sh script that I need to run every 60 seconds? – Izy- – 2016-09-13T05:16:08.077

It's a unit file for systemd. It doesn't call your script. It repeatedly starts the corresponding .service, which then calls your script. – user1686 – 2016-09-13T05:16:53.437

So my initial log_info.service file must still exist then? And I still don't understand where this foo.timer is calling my other log_info service file, if that's the case – Izy- – 2016-09-13T07:01:09.487

If the names differ, you specify the service unit's name in [Timer] Unit=. Otherwise foo.timer will try to look for foo.service by default. – user1686 – 2016-09-13T07:10:18.053

Thanks grawity. Last question, in my log_info.service, I call my ss.sh right? – Izy- – 2016-09-14T06:55:35.050