halloICKEbins
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Mahlzeit, ich würde gerne in meinen eigenen Script prüfen, ob es schon läuft. Ich wurde es gerne mit os.path.basename(sys.argv[0]) irgendwie lösen ohne auf Shell-Befehle zurückgreifen zu müssen. Hintergrund ist, dass ich mittels Cronjob ein Script jede Minute starte in welchem mein oben beschriebenes Script alle 5 Sekunden aufgerufen wird. wenn es noch läuft soll das neu aufgerufene Script nicht weiter laufen! 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | ...
(sleep 5 && script_function) &
(sleep 10 && script_function) &
(sleep 15 && script_function) &
(sleep 20 && script_function) &
(sleep 25 && script_function) &
(sleep 30 && script_function) &
(sleep 35 && script_function) &
(sleep 40 && script_function) &
(sleep 45 && script_function) &
(sleep 50 && script_function) &
(sleep 55 && script_function) &
(sleep 60 && script_function)
...
|
Ist das zu umständlich oder gibt es andere Möglichkeiten? Bearbeitet von rklm: Arrayindex repariert
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13175
|
halloICKEbins schrieb:
ich würde gerne in meinen eigenen Script prüfen, ob es schon läuft.
Wenn ich das richtig verstehe, ist Dein Ziel in erster Linie, dass ein Skript nicht mehr als ein Mal gleichzeitig läuft.
Ich wurde es gerne mit os.path.basename(sys.argv[0]) irgendwie lösen ohne auf Shell-Befehle zurückgreifen zu müssen. Hintergrund ist, dass ich mittels Cronjob ein Script jede Minute starte in welchem mein oben beschriebenes Script alle 5 Sekunden aufgerufen wird. wenn es noch läuft soll das neu aufgerufene Script nicht weiter laufen!
Das ist aber sehr redundant:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | ...
(sleep 5 && script_function) &
(sleep 10 && script_function) &
(sleep 15 && script_function) &
(sleep 20 && script_function) &
(sleep 25 && script_function) &
(sleep 30 && script_function) &
(sleep 35 && script_function) &
(sleep 40 && script_function) &
(sleep 45 && script_function) &
(sleep 50 && script_function) &
(sleep 55 && script_function) &
(sleep 60 && script_function)
...
|
Dann lieber | for i in {5..60..5}; do
sleep $i && script_function &
done
|
Ist das zu umständlich oder gibt es andere Möglichkeiten?
Du kannst das auch mit Dateisperren erreichen. Dann kann es auch keine Race-Conditions geben, wie bei Deinem angedachten Ansatz, zu schauen, ob es einen Prozess mit dem selben Pfad gibt wie der aktuelle.
|
frostschutz
Anmeldungsdatum: 18. November 2010
Beiträge: 7782
|
mkdir /tmp/dingenskirchens && ./kirche_im_dorf_lassen.sh; rmdir /tmp/dingenskirchens oder while :
sleep 5 &
script
wait # for sleep
done oder while sleep $((5 - $(date +%s) % 5))
do
script
done
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13175
|
frostschutz schrieb: mkdir /tmp/dingenskirchens && ./kirche_im_dorf_lassen.sh; rmdir /tmp/dingenskirchens
Das ist falsch! Wenn das Verzeichnis besteht, wird zwar das Kirchenskript nicht gestartet, aber das Verzeichnis wird gelöscht. Das müsste dann eher so aussehen: | d=/tmp/dingenskirchens
if mkdir "$d" then
./kirche_im_dorf_lassen.sh
rmdir "$d"
fi
|
Aber wenn man schon ein Shell-Skript nimmt, dann würde ich eher das Locken benutzen, weil das nur an dem Vorhandensein des Prozesses hängt. Ich habe ein entsprechendes Shell-Skript auf meiner Benutzerseite-
while :
sleep 5 &
script
wait # for sleep
done
Syntaxfehler.
while sleep $((5 - $(date +%s) % 5))
do
script
done
Interessanter Ansatz! Ich würde generell die Ausführung alle fünf Sekunden und Cron nicht mischen. Ggf. hat Systemd feinere Auflösung als Cron (1 Minute) und man könnte das darüber regeln. Sonst würde ich eher einen Prozess starten, der ewig läuft und alle fünf Sekunden etwas macht, so, wie das z.B. vmstat und iostat auch tun. Das hat den Vorteil, dass man nicht jedes Mal den Overhead der Prozesserzeugung hat.
|
frostschutz
Anmeldungsdatum: 18. November 2010
Beiträge: 7782
|
rklm schrieb: Das ist falsch!
Gut aufgepasst... den hinteren Teil kann man in Klammern setzen, dann passt es wieder.
| d=/tmp/dingenskirchens
if mkdir "$d" then
./kirche_im_dorf_lassen.sh
rmdir "$d"
fi
|
Syntaxfehler. 😛 🙄
Ich würde generell die Ausführung alle fünf Sekunden und Cron nicht mischen.
Vor allem muss man bedenken daß Cron selbst das Zeug nicht sekundengenau ausführt. Cron ist für grobe Sachen. Wer Sekundengenauigkeit braucht, ist mit einem eigenen Dienst - der dann durchläuft und nicht jede Minute gestartet werden muss - einfach viel besser unterwegs. Ich wollte mit meinem Beitrag nur einen Denkansatz liefern, was tatsächlich funktioniert, das durchzupuzzeln muss man selbst. 😉
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13175
|
frostschutz schrieb:
Syntaxfehler. 😛 🙄
😀
Vor allem muss man bedenken daß Cron selbst das Zeug nicht sekundengenau ausführt. Cron ist für grobe Sachen. Wer Sekundengenauigkeit braucht, ist mit einem eigenen Dienst - der dann durchläuft und nicht jede Minute gestartet werden muss - einfach viel besser unterwegs.
👍
Ich wollte mit meinem Beitrag nur einen Denkansatz liefern, was tatsächlich funktioniert, das durchzupuzzeln muss man selbst. 😉
Jo.
|
NORACSA
Anmeldungsdatum: 31. Januar 2010
Beiträge: 180
|
rklm schrieb: frostschutz schrieb: mkdir /tmp/dingenskirchens && ./kirche_im_dorf_lassen.sh; rmdir /tmp/dingenskirchens
Das ist falsch! Wenn das Verzeichnis besteht, wird zwar das Kirchenskript nicht gestartet, aber das Verzeichnis wird gelöscht. Das müsste dann eher so aussehen: | d=/tmp/dingenskirchens
if mkdir "$d" then
./kirche_im_dorf_lassen.sh
rmdir "$d"
fi
|
Ist das nicht ein bisschen mit Kanonen auf Spatzen geschossen? Im Grunde müsste es reichen wenn man alle Befehle per && verknüpft. Dann wird das Verzeichnis zwar nur gelöscht wenn der 2. Befehl auch korrekt durchläuft, aber das will man ja eigentlich eh, oder?
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
Ich hätte gehofft, dass es einfacher zu bewerkstelligen ist, wie ...
| flock -n 9 || {
echo "ERROR: already running - exiting." >&2
exit 1
}
|
... allerdings in Python.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13175
|
NORACSA schrieb: rklm schrieb:
| d=/tmp/dingenskirchens
if mkdir "$d" then
./kirche_im_dorf_lassen.sh
rmdir "$d"
fi
|
Ist das nicht ein bisschen mit Kanonen auf Spatzen geschossen?
Was jetzt genau?
Im Grunde müsste es reichen wenn man alle Befehle per && verknüpft. Dann wird das Verzeichnis zwar nur gelöscht wenn der 2. Befehl auch korrekt durchläuft, aber das will man ja eigentlich eh, oder?
Ich hätte gesagt nein, weil dann der ganze Prozess steht. Aber das weiß nur halloICKEbins. halloICKEbins schrieb:
... allerdings in Python.
Ich hatte doch den Link auf die Doku geschickt...
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11248
Wohnort: München
|
Das könnte man z.B. mit GLib umsetzen (gi bzw. GLib steckt im Paket python3-gi), Zeile 6 ersetzt man dann mit dem Aufruf der gewünschten Funktion bzw. Methode aus dem Python-Skript, die periodisch aufgerufen werden soll:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | #!/usr/bin/env python3
import time
from gi.repository import GLib
def callback():
print(time.time(), "do something")
return True
if __name__ == '__main__':
loop = GLib.MainLoop() # https://developer.gnome.org/pygobject/stable/class-glibmainloop.html
try:
GLib.timeout_add_seconds(5, callback) # https://developer.gnome.org/pygobject/stable/glib-functions.html#function-glib--timeout-add-seconds
loop.run()
except KeyboardInterrupt:
raise SystemExit("Interrupted")
|
Mit GLib.timeout_add statt GLib.timeout_add_seconds kann man eine etwas größere Genauigkeit erzielen, ähnlich wie sleep in der Shell ist das aber nicht für präzises Timing gedacht. Edit: damit bekommt man allerdings kein 5 Sekunden-Raster, wenn die Ausführung des Callbacks länger als 5 Sekunden dauert, sondern der nächste Aufruf passiert zeitnah und nachfolgende Aufrufe dann wieder in 5 Sekunden-Abständen, wenn sie nicht zu lange brauchen. Wenn man näher an ein 5-Sekunden Raster kommen will, könnte man z.B. sowas machen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | #!/usr/bin/env python3
import time
from gi.repository import GLib
def callback():
t = time.time()
if round(t) % 5 == 0:
print(t, "do something")
return True
loop = GLib.MainLoop()
try:
GLib.timeout_add_seconds(1, callback)
loop.run()
except KeyboardInterrupt:
raise SystemExit("Interrupted by User")
|
|
halloICKEbins
(Themenstarter)
Anmeldungsdatum: 12. September 2017
Beiträge: 226
|
rklm schrieb: Ich hatte doch den Link auf die Doku geschickt...
Ja, danke dafür aber leider bin ich nicht schlauer damit geworden 😳
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13175
|
halloICKEbins schrieb: rklm schrieb: Ich hatte doch den Link auf die Doku geschickt...
Ja, danke dafür aber leider bin ich nicht schlauer damit geworden 😳
Du öffnest eine Datei zum Lesen und lockst sie dann. Wenn der Prozess terminiert (aus welchem Grund auch immer) räumt der Kernel das Lock weg. Fertig ist die Laube. Du musst Dich nur auf die Datei einigen, das könnte z.B. das Skript selbst sein. Oder das Home des aktuellen Nutzers, wenn Du den Prozess nur ein Mal pro Benutzer haben willst.
|