Seite 1 von 1

Django: Script losgelöst starten

Verfasst: Mittwoch 1. August 2018, 14:31
von jb_alvarado
Hallo Allerseits,
ich suche eine Möglichkeit wie ich mittels Django ein separates Python Script starten kann, das komplett losgelöst von Django läuft. Also selbst wenn ich den Django Server stoppe sollte es weiter laufen.

Was ich schon versucht habe:
  • Eine Methode mit doppeltem os.fork()
  • Code: Alles auswählen

    Popen(['nohup, ''python', backup.py, '&'], close_fds=True)
  • python-daemon
In einem separaten Script, ohne Django läuft das alles auch wunderbar, nur sobald ich das ganze in Django ausführe klappt es nicht mehr.

Auf Celery und Ähnliches würde ich gerne verzichten.

Habt ihr einen Tipp für mich, wie ich das lösen kann?

Re: Django: Script losgelöst starten

Verfasst: Mittwoch 1. August 2018, 14:49
von Sirius3
Ich sehe keinen Grund, warum sich das System anders verhalten sollte, wenn es sich um ein Django-Programm handelt. Das '&' ist ein Bash-Sonderzeichen und macht beim direkten exec keinen Sinn, das wird so als Parameter an backup.py übergeben, wo es wahrscheinlich ignoriert wird.

Startest Du den Server über `systemd`? Dann hilft vielleicht Systemd: keep forked process alive when service is stopped.

Re: Django: Script losgelöst starten

Verfasst: Mittwoch 1. August 2018, 14:53
von DasIch
Vereinfachtes Celery: Cronjob der jede Minute läuft und wenn eine bestimmte Datei vorhanden diese löscht und dein backup.py Skript ausführt. Du triggerst dies indem du von Django aus einfach diese Datei erstellst.

Damit kann dein backup.py auch unter einem anderen User mit mehr Rechten als deine Django Anwendung laufen. Außerdem umgeht dies alle möglichen Probleme die durch Concurrency entstehen können.

Re: Django: Script losgelöst starten

Verfasst: Mittwoch 1. August 2018, 16:05
von jb_alvarado
Ich danke euch für die Antworten!

@Sirius3, ich verstehe auch nicht warum sich das unter django anders verhält... Momentan starte ich den Server noch über: python manage.py runserver, später läuft gunicorn über systemd gestartet.

@DasIch, dein Vorschlag klingt eigentlich ziemlich gut! Werde mir das mal durch den Kopf gehen lassen.

Womit ich es jetzt hinbekommen habe ist das hier:

Code: Alles auswählen

p = Popen(['python', 'backup.py'], close_fds=True, preexec_fn=os.setpgrp)

return p.pid
Muss noch testen ob das wirklich sicher läuft. Mit dem ganzen sollen Tapes bespielt werden, da wäre es unschön wenn der Vorgang abbricht.

Re: Django: Script losgelöst starten

Verfasst: Mittwoch 1. August 2018, 20:46
von __deets__
Ich glaube systemd ist hier das Problem. Das packt alles in eine Prozess Gruppe, und wenn deren “Kopf” stirbt, wird auch alles andere beendet.

Ggf kannst du das in der systemd Unit einstellen:

https://unix.stackexchange.com/question ... s-spawning

Re: Django: Script losgelöst starten

Verfasst: Sonntag 5. August 2018, 20:56
von noisefloor
Hallo,

ich würd's so probieren, dass das "2. Skript" über eine systemd Unit gestart wird, die mittels der `After` Direktive nach der Gunicorn-Unit (und damit Django) startet. Dann sollte die Unit auch weiter leben, wenn die Gunicorn-Unit beendet wird.

Gruß, noisefloor

Re: Django: Script losgelöst starten

Verfasst: Dienstag 7. August 2018, 12:18
von jb_alvarado
Zum Zeitpunkt des Testens war systemd noch nicht das Problem, das hatte ich ja gar nicht verwendet. Allerdings wäre es später sicher zum Problem geworden, weil ich nicht wusste, dass es Kindprozesse mit stoppt, wenn der Elternprozess schließt.

Habe wie vorgeschlagen "KillMode=process" zum Service File hinzugefügt.

Danke für den Hinweis noch mal!

Re: Django: Script losgelöst starten

Verfasst: Dienstag 4. September 2018, 07:28
von jens
Ein vereinfachtes celery ist django autotask: https://bitbucket.org/kbr/autotask

Allerdings gibt es zumindest ein ungelöstes Problem über welches ich auch gestolpert bin: https://bitbucket.org/kbr/autotask/pull-requests/3/

Re: Django: Script losgelöst starten

Verfasst: Dienstag 4. September 2018, 08:23
von kbr
@jens: Vor einer Migration muss in den settings 'AUTOTASK_IS_ACTIVE = False' gesetzt werden; das geschieht nicht automatisch, ist aber mittlerweile dokumentiert. Zugegeben, das ist unschön, wenn man nicht daran denkt. Lässt sich in den settings aber leicht einprogrammieren, falls das für eine Anwendung wichtig ist.

Allerdings fährt autotask runter, wenn der zugehörige django-Prozess gestoppt wird. Insofern ist es keine Lösung für den TE.