Schreiben von Python-Bedingungen für Crontab

Aug 21 2020

Wie funktioniert eine Python-if-Anweisung beim Bearbeiten in crontab? Verwenden von Python 3.6.3

Mit Linux Crontab versuche ich, die Anzahl der versteckten Dateien in einem Verzeichnis (außer den Verzeichnissen "." Und "..") zu ermitteln, damit ich eine Warnung planen kann. Folgendes gibt den Betrag im Zeichenfolgenformat ab:

import subprocess
res = subprocess.run('ls -Ap | egrep "^\..*/$" | wc -l', shell=True, universal_newlines=True, stdout=subprocess.PIPE);
print(res.stdout)

output>>> (integer type string)

Dann möchte ich so etwas wie

if res.stdout != "0":
   (executeAlert.sh script)
else:
   (ignore)

Jede Hilfe wird geschätzt.

Antworten

1 tripleee Aug 21 2020 at 14:43

Eine viel bessere Lösung besteht darin, einen Teilprozess vollständig zu vermeiden. (Und selbst wenn Sie einen Unterprozess verwenden, verwenden Sie ihn nicht lsin Skripten.)

from pathlib import Path

dotfiles = Path().glob('.[!.]*')
if len(list(dotfiles)) > 0:
    do_things()

Tatsächlich besteht keine wirkliche Notwendigkeit, die Länge zu überprüfen; Sie können sagen

dotfiles = list(Path().glob('.[!.]*'))
if dotfiles:
    do_things('The files which matched are %s' % dotfiles)

Etwas dunkel, aber prägnanter, könnten Sie stattdessen über den Generator iterieren. Der Schleifenkörper wird nur ausgeführt, wenn mindestens eine übereinstimmende Datei vorhanden ist. Dies ist eine Optimierung, wenn Sie sich nur darum kümmern, ob mindestens eine Datei vorhanden ist, da diese angehalten wird, sobald die erste gefunden wurde.

for file in Path().glob('.[!.]*'):
    do_things()
    break

Python ist es egal, ob Sie Ihr Skript ausführen cronoder nicht (obwohl Sie manchmal die Umgebung für Python in Ihrem cronJob einrichten müssen, wenn Bibliotheken an nicht standardmäßigen Speicherorten installiert sind). Aber warum verwenden Sie hier überhaupt Python, wenn Ihre gesamte Geschäftslogik in Shell-Skripten enthalten ist? (Obwohl Ihr Shell-Scripting auch davon profitieren könnte, einige Antimuster zu studieren , um dies zu vermeiden.)

Hier ist das Ganze vollständig in Shell-Skript, mit ähnlicher Logik:

for file in .[!.]*; do
    test -e "$file" || break  # cf nullgbob
    executeAlert.sh
    break
done

Bash bietet shopt -s nullgloban, das Betreten der Schleife zu vermeiden, wenn der Platzhalter nicht übereinstimmt. aber cronläuft shund es ist nicht ganz schwer bashisms hier zu vermeiden (obwohl das Globbing Verhalten in dem Fall ohne Streichhölzer ist überraschend).

Wenn Sie alle Übereinstimmungen in einem Shell-Skript möchten, können Sie sagen

set -- .[!.]*
if [ "$@" != ".[!.]*" ]; then
    executeAlert.sh "$@"   # argument is list of matching files
fi

Wenn Sie Bash oder ksh verwenden, können Sie die Übereinstimmungen in einem Array sammeln.

shopt -s nullglob
dotfiles=(.[!.]*)
for file in "${dotfiles[@]}"; do
   echo "Here's one dotfile: $file" done if [[ "${#dotfiles[@]}" > 0 ]]; then
     executeAlert.sh "${dotfiles[@]}"
fi

Ihre egrepRegex würde nur in Punktverzeichnissen übereinstimmen . Ich habe angenommen, dass dies ein Fehler war.

Oneiros Aug 21 2020 at 14:03

Beim Drucken res.stdoutwird angezeigt, dass ein Endzeilenzeichen enthalten ist.

>>>res.stdout
'0\n'

Entfernen Sie einfach das Zeichen '\ n':

res = res.stdout.strip('\n')
if res == "0":
    (executeAlert.sh script)

Alternativ können Sie es auch als Ganzzahl umwandeln:

if int(res.stdout) == 0:
    (executeAlert.sh script)