Django: Script losgelöst starten

Django, Flask, Bottle, WSGI, CGI…
Antworten
jb_alvarado
User
Beiträge: 55
Registriert: Mittwoch 11. Juli 2018, 11:11

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?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

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.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

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.
jb_alvarado
User
Beiträge: 55
Registriert: Mittwoch 11. Juli 2018, 11:11

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.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

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
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

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
jb_alvarado
User
Beiträge: 55
Registriert: Mittwoch 11. Juli 2018, 11:11

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!
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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/

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@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.
Antworten