Schreiben von Python-Bedingungen für Crontab
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
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.
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)