virtualenv und cron?

  • Hallo,


    ich habe 8 Python Scripts, die regelmäßig (jede Stunde zu bestimmter Uhrzeit, genaue Zeit variiert pro Script) per cron gestartet werden.
    Die Scripts laufen relativ lange und ich habe das Gefühl, dass maximal zwei Scripts parallel laufen können; sollten andere Scripts noch laufen, werden diese abgebrochen bzw. zumindest arbeiten sie nicht mehr effektiv.


    Nun würde ich gerne für jedes Script eine virtuelle Umgebung schaffen, unter dieser das Script laufen kann; Also
    Script 1 15 * * * * in virtual1
    Script 2 20 * * * * in virtual2
    Script 3 25 * * * * in virtual3
    usw.


    Sodass sich die Scripts nicht gegenseitig behindern. Langfristig möchte ich alle Scripts (die sowieso dasselbe tun, aber jeweils für einen anderen Benutzer) in ein Script zusammenfassen; dies kann aber noch dauern, da ich sie hierfür von Grund auf neu schreiben muss bzw. möchte, um besseren Stil (Funktionen statt viel zu viele Codezeilen etc.) im fertigen Script zu haben.


    Wie führe ich das am Besten durch? Zu virtualenv und cron konnte ich kein gutes Tutorial finden...


    Danke & LG

  • Die Scripts holen Werte via HTTP GET, verarbeiten diese und senden sie dann per HTTP POST an einen Server. Komischerweise funktionieren ja aber zwei Scripts parallel (die alle dasselbe tun, nur für andere Usernames), aber nicht alle auf einmal. Wenn sie in einer virtuellen Umgebung laufen, sollten sie sich doch generell nicht gegenseitig behindern, oder?

  • Ich glaube du hast ein etwas mystisches Bild dessen, was ein virtualenv ist und was nicht. Ich setze sie gerne und regelmaessig ein, und fuer dein Problem gibt es auch eine simple Loesung - in Bezug darauf, die Skripte in verschiedenen VENVs laufen zu lassen. Alles, was dazu noetig ist, ist als erstes Argument nicht nur "python", sondern den vollen Pfad zum VENV-Python anzugeben - also zB /home/pi/venvs/v1/bin/python. Dadurch wird automatisch das VENV benutzt.


    Doch das wird dir funktional keine Verbesserung bringen. VENVs dienen dazu, Python-Pakete in verschiedenen Versionen parallel betreiben zu koennen. Bei mehrmaligem das gleiche Skript mit den gleichen Operationen und Abhaengkeiten laufen zu lassen ergibt das aber keinerlei Unterschied.


    Ohne Code kann man nun schwer beurteilen, warum sich mehr als zwei Skripte bei dir nun so ausbremsen.

  • das immer nur ein script ist recht einfach zu realisieren mit lockfile, lockdir, pidfiles.
    z.b. script1 laeuft und erstellt ein file run.irgendwas, script2 will starten und prueft ob run.irgendwas a ist.
    mit 2 sollte das auch einfach sein.
    da gibs auch umfangreiche loesungen, must nach mutex suchen.


    ich mach sowas auch, wenn was mit mail laeuft wird kein backup gestartet, backup scripts laufen nacheinander, wenn nebenbei das system benutzbar sein soll ist es sinnvoller 1 std 100% auslastung als 1 std 500 %.
    wenn alles gleichzeitig laeuft ist es auch nicht schneller fertig.

  • Ein bisschen komplizierter als nur Dateien anzulegen ist das schon - ich hab' mal einen contextmanager dafuer gebaut: https://github.com/AbletonAG/a…ster/abl/util/lockfile.py


    Denn wenn dein Prozess stirbt, ohne dass er die Datei entfernt hat, blockieren die anderen bis in alle Ewigkeiten :)


    Aber ich glaube kaum, das dem TE das wirklich hilft. Er koennte sonst ja auch einfach ueber cront staffeln. Da scheint was prinzipielles im Argen zu liegen.


  • Ein bisschen komplizierter als nur Dateien anzulegen ist das schon - ich hab' mal einen contextmanager dafuer gebaut: https://github.com/AbletonAG/a…ster/abl/util/lockfile.py


    Denn wenn dein Prozess stirbt, ohne dass er die Datei entfernt hat, blockieren die anderen bis in alle Ewigkeiten :)


    pruefen ob der process gestorben ist? echo $$ > pidfile beim starten.
    naechster process
    otherpid="$(cat "${pid_file}")
    dann mit ps -h --pid ${otherpid} testen.


    zu kompliziert, web-suche bemuehen:
    for ((i = 0; i < 2; i = i + 1)); do
    ln -sn $$ ${LOCKFILE} 2>/dev/null && break
    cronpid=$(readlink ${LOCKFILE} 2>/dev/null) || cronpid=$(cat ${LOCKFILE} 2>/dev/null) || continue
    if [[ $(</proc/${cronpid}/cmdline) == $(</proc/$$/cmdline) ]] 2>/dev/null; then
    exit 0 # ein anderer process laeuft
    else rm -f ${LOCKFILE}; fi
    done


    andere programmiersprachen spar ich mir, fuer jmd der web-browser hat sollte nix einfacher sein sowas zu finden.



    Aber ich glaube kaum, das dem TE das wirklich hilft. Er koennte sonst ja auch einfach ueber cront staffeln. Da scheint was prinzipielles im Argen zu liegen.


    was wir wohl erst beurteilen können wenn er mehr infos gibt oder source postet.

  • Er möchte aber doch die Scripts PARALLEL ausführen, also mehrere GLEICHZEITIG.


    Er schrieb, dass 2 Scripts parallel auszuführen funktioniert, aber nicht alle auf ein mal. Mit "alle" meint er 8 Python Scripts.


    Was soll er dann bitte mit LOCKFILE usw anfangen? :s Das geht in die Falsche Richtung. Also hilft dem TE der Vorschlag von adora in keinster Weise.



    raspberry314 schreibt aber auch das die Scripts "sowieso dasselbe tun, aber jeweils für einen anderen Benutzer"... aber dann auch weiter schreibt "in ein Script zusammenfassen; dies kann aber noch dauern, da ich sie hierfür von Grund auf neu schreiben muss"
    ^- Nein nicht wirklich ;) Es bedarf dann eigentlich nur ein paar kleinerer Änderungen - wobei wir natürlich nicht wissen wie die Scripts genau aussehen, aber wenn das 8 identische Scripts sind nur unterschiedliche Benutzer die behandelt werden, umfasst die Anpassungen wirklich nur 3-5 Zeilen.

  • Code
    LISTOFFILES=$(find "/home/"  -maxdepth 1 -name "*" -type d)
    for PATHOFILE in $LISTOFFILES ; do
        user_param=${PATHOFILE##*/}
        /sbin/runuser -u $user_param userscript
    done



    oben nochmal ein beispiel von mir um einmal im monat maillogs zu packen/sichern/loeschen, alle user nacheinander, so muss ich auch nicht 25 user crontabs pflegen sondern nur den fuer root, und wenn alle am monatsanfag um 0:00 gleichzeitig starten wuerden behindern die sich wirklich gegenseitig.


    aber linux ist ein multiuser/multitasking BS und darauf ausgelegt das mehrere Sachen laufen, funktioniert auch gut. ich wuerd nur drauf achten das nicht alles was 100% systemlast hat gleichzeitig laeuft.




    Langfristig möchte ich alle Scripts (die sowieso dasselbe tun, aber jeweils für einen anderen Benutzer) in ein Script zusammenfassen; dies kann aber noch dauern, da ich sie hierfür von Grund auf neu schreiben muss bzw. möchte, um besseren Stil (Funktionen statt viel zu viele Codezeilen etc.) im fertigen Script zu haben.


    jo , kenn ich, ich schreib schnell was, es funktioniert, und monate spaeter wenn ich was aendern muss frag ich mich was ich da fuern scheiss gemacht hab, kostet dann zeit wieder durchzusteigen.


    ein script fuer alle user sollte aber schnell gehn, user als parameter uebergeben wie oben, oder als user im cron starten, im programm evt. user abfragen, home verzeichnis des users aufrufen etc..

  • Dein Beispiel ist für bash, er hat aber python. Ohne das Script zu sehen bringen solche Beispiele nicht viel - könne ich auch etliche Beispiele zu posten