0

I need to create a script that will execute daily (cron job), calculate the uptime of the system, and if that number is greater than 72 hours, reboot the system.

I am getting lost in converting the value of hours to something I can compare to 72. It returns me 6499.04: command not found

#!/bin/bash
if $(awk '{print $1}' /proc/uptime) / 3600 > 72 ; then
    echo "yes"                                                                                                                                                                        
fi

Thank you in advance for any help!

Dynameyes
  • 111
  • 2

5 Answers5

7

I would do the whole test in AWK:

awk '$1 > (72 * 3600) { print "yes" }' /proc/uptime

If you want to use that as a test, use the exit code:

if awk '{ exit ($1 < (72 * 3600)) }' /proc/uptime; then
    echo Need to reboot
fi

AWK evaluates ($1 < (72 * 3600)) as 0 if the comparison fails, 1 otherwise; 0 indicates success as an exit code, so we invert the condition.

If you’re using systemd, another approach would be to use a systemd timer, with OnBootSec=72h (see FelixJN’s answer for details).

Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
6

A systemd timer would work, too:

[Unit]
Description=reboot after 72h
 
[Timer]
Unit=systemd-reboot.service
OnBootSec=72h

[Install]
WantedBy=multi-user.target

Note that this is not a service, but a timer, i.e. the file name must end in .timer. Put it in e.g. /etc/systemd/system/reboot27h.timer, then enable and start it it for the current session as usual:

systemctl enable reboot72h.timer
systemctl start reboot72h.timer

To check if the timer works properly and how much time is left until the next run, use

systemctl list-timers
FelixJN
  • 12,616
  • 2
  • 27
  • 48
  • Because my question was more about correcting my bash script, I felt that the correct answer was @Stephen Kitt. But this solution is way more clean and elegant. – Dynameyes Sep 15 '21 at 15:57
2

Your script has several syntax errors in the if condition which leads to the error message you are getting.

  1. In the if condition, you need a command or a bash builtin test construct that returns 0 (=true) on success and non-zero (=false) on failure. You chose to perform an arithmetic comparison, so you need to place it in the appropriate test construct:
    if (( variable1 > variable2 )); then .... ; fi
    
  2. You use process the content of uptime, which contains a floating-point number. Bash however is not able to perform floating-point arithmetic, so such expressions will not work as expected.
  3. Because you didn't place the condition in the test construct, Bash considers the result of your awk text-processing as a command to be executed, so it tries to "execute" the current uptime (the reason for the error message).

To alleviate, you could truncate the seconds to an integer value by using the first . as field separator. So, you could try

up=$(awk -F. '{print $1}' /proc/uptime)
if (( up > 72*3600 )); then echo "yes"; else echo "no"; fi

Please note

  • The question is tagged , so I used the bash-specific (( ... )) test construct. If you want the script to be portable, you have to use the POSIX-compliant
    if [ $up -gt 259200 ]; then ...; else ...; fi
    
  • As a general rule, I would recommend you to run your shell scripts through shellcheck, also available as standalone program on many Linux distributions, to catch syntax errors and the like.
AdminBee
  • 21,637
  • 21
  • 47
  • 71
1

You can do all this in bash by converting dates into timestamps and do some calculations. You can use uptime -s so no need for awk or anything else

#!/usr/bin/env bash

upt=$(date -d "$(uptime -s)" +%s)
hours=$(date -d '72 hours ago' +%s)

if (( upt < hours)); then echo "System up for at least 72h"; else echo "Nothing to do"; fi
Valentin Bajrami
  • 9,244
  • 3
  • 25
  • 38
0
#! /bin/bash

if [ $(awk '{print int($1/3600)}' /proc/uptime) -gt 72 ]; then
    echo "yes"
fi
Artem S. Tashkinov
  • 26,392
  • 4
  • 33
  • 64