ubuntuusers.de

Abschnitt im Bash-Skript nur einmal täglich/stündlich ausführen?

Status: Gelöst | Ubuntu-Version: Xubuntu 20.04 (Focal Fossa)
Antworten |

Udalrich

Anmeldungsdatum:
15. Mai 2019

Beiträge: 533

Mein kleines Bash-Skript starte ich per Doppelklick bei Bedarf. Gewisse Abschnitte darin sollen immer ausgeführt werden, deswegen möchte ich kein Cron.

Doch ein gewisser Abschnitt im gleichen Skript bräuchte nur einmal täglich oder alle X Stunden dranzukommen und die restliche Zeit übergangen werden, wenn ich das Skript doppelklicke.

Wie könnte man das am elegantesten lösen, ohne das Rad neu zu erfinden und ein Sechseck zu erhalten?

So in der Art: if <heute noch nicht gelaufen> oder <schon x Stunden vergangen> dann...

#!/bin/bash

# Abschnitte, die immer drankommen sollen.
rsync immer

# Folgender Abschnitt soll nur einmal täglich oder alle X Stunden drankommen.
if ping -w 1 Pi >/dev/null ; then
   rsync manchmal
fi

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4476

Wohnort: Göttingen

Hm, Du könntest Dir die Uhrzeit der Ausführung in eine Datei speichern und dann bei einer erneuten Ausführung vergleichen.

Udalrich

(Themenstarter)

Anmeldungsdatum:
15. Mai 2019

Beiträge: 533

Das ist eine gute Idee. Danke.

Doch wie realisiert man dies in Bash? In AWK mit seiner C-ähnlichen Syntax könnte ich es programmieren, aber die Bash-Syntax scheint mir ewig fremd zu bleiben.

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4476

Wohnort: Göttingen

Datum in Variable speichern:

date +%Y%m%d%H%M%S > ~/stampfile

Datum aus Datei in Variable $date einlesen:

date=$(< ~/stampfile)

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11311

Wohnort: München

Ich würde das als Unix-Timestamp speichern, dann muss man nur die Differenz mit dem aktuellen Timestamp bilden und schauen, ob das größer als der gewünschte Zeitraum ist - also z.B.:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/bin/bash
declare -i now=$(date +%s)
declare -i last_run

touch last_run.txt
last_run=$(<last_run.txt)
declare -i min_delta=$(( 60 * 60 )) # 60 Minutes à 60 seconds = one hour

if (( (now - last_run) > min_delta ))
then
    echo "last run was at least $min_delta seconds ago"
fi
echo $now > last_run.txt

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13370

seahawk1986 schrieb:

Ich würde das als Unix-Timestamp speichern, dann muss man nur die Differenz mit dem aktuellen Timestamp bilden und schauen, ob das größer als der gewünschte Zeitraum ist - also z.B.:

Cooler Trick durch das Deklarieren von last_run als Integer den Edge-Case vom ersten Aufruf abzufangen!

Ich bevorzuge je eher, den Zeitstempel einer leeren Datei zu nutzen anstatt in sie hinein zu schreiben. Wobei das bei modernen Dateisystemen, die kleine Dateien im Inode speichern, vermutlich keinen Unterschied in der Speichereffizienz macht. Bei mir wäre das eher

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh

set -e # fast exit, ensures file's timestamp is only modified in case of success

interval=$((60 * 60)) # 1 hour
last_file=~/.last

now=$(date +%s)

# variant 1
last=0
[ -r "$last_file" ] && last=$(date +%s -r "$last_file")

# variant 2
last=$(date +%s -r "$last_file") || last=0

if [ $((now - last)) -gt $interval ]; then
  # do the work
  touch "$last_file"
fi

Udalrich

(Themenstarter)

Anmeldungsdatum:
15. Mai 2019

Beiträge: 533

Nun habe ich zuerst einmal Seahawks Variante probiert und sie funktioniert hervorragend.
Rklms Idee mit dem Zeitstempel statt Reinschreiben ist auch sehr gut.

Vielen Dank an Doc_Symbiosis für die Starthilfe, an Seahawk für die Perfektionierung und an Rklm für die Verfeinerung!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13370

Ich hätte vielleicht noch erwähnen sollen, dass ich den Abschnitt in ein separates Skript auslagern würde - zumindest, wenn das ohne größere Umstände möglich ist. Die "seltene" Tätigkeit ist ja vermutlich in sich abgeschlossen.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17674

Wohnort: Berlin

rklm schrieb:

Ich hätte vielleicht noch erwähnen sollen, dass ich den Abschnitt in ein separates Skript auslagern würde - zumindest, wenn das ohne größere Umstände möglich ist. Die "seltene" Tätigkeit ist ja vermutlich in sich abgeschlossen.

Das wäre auch meine Idee.

immer.sh:

1
Code der immer ausgeführt werden soll.

taeglich.sh:

1
2
3
source immer.sh

# Code der nur 1x tgl. werden soll.

In der Crontab rufst Du taeglich.sh auf, welches immer.sh inkludiert. Mit Klicken startest Du die immer.sh.

Antworten |