Pisanie warunków warunkowych Pythona dla crontab

Aug 21 2020

Jak działa instrukcja Python if podczas edytowania jej w crontab? Korzystanie z Pythona 3.6.3

Używając linux crontab próbuję policzyć liczbę ukrytych plików w katalogu (innym niż katalogi „.” I „..”), aby móc zaplanować alert. Następujące pobiera kwotę w formacie ciągu:

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)

Wtedy chcę coś takiego

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

Każda pomoc jest mile widziana.

Odpowiedzi

1 tripleee Aug 21 2020 at 14:43

Znacznie lepszym rozwiązaniem jest całkowite uniknięcie podprocesu. (Nawet jeśli używasz podprocesu, nie używaj lsw skryptach).

from pathlib import Path

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

W rzeczywistości nie ma potrzeby sprawdzania długości; możesz powiedzieć

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

Nieco niejasno, ale bardziej zwięźle, możesz zamiast tego powtórzyć generator; treść pętli zostanie wykonana tylko wtedy, gdy istnieje co najmniej jeden pasujący plik. Jest to optymalizacja, jeśli zależy Ci tylko na tym, czy istnieje co najmniej jeden plik, ponieważ zatrzymuje się po znalezieniu pierwszego;

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

Pythona nie obchodzi, czy uruchamiasz swój skrypt z cronczy nie (chociaż czasami musisz zaaranżować środowisko dla Pythona w swoim cronzadaniu, jeśli masz biblioteki zainstalowane w niestandardowych lokalizacjach). Ale dlaczego w ogóle używasz tutaj Pythona, skoro cała logika biznesowa znajduje się w skryptach powłoki? (Chociaż twoje skrypty powłoki mogą również skorzystać na przestudiowaniu niektórych antywzorów, których należy unikać.)

Oto cała sprawa w skrypcie powłoki, przy użyciu podobnej logiki:

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

Bash oferuje shopt -s nullglobuniknięcie wejścia do pętli, jeśli symbol wieloznaczny nie pasuje; ale cronbiegnie shi nie jest tu całkiem trudno uniknąć bashizmów (chociaż zachowanie globbingu w przypadku braku dopasowań jest zaskakujące).

Jeśli chcesz wszystkie dopasowania w skrypcie powłoki, możesz powiedzieć

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

Jeśli używasz Bash lub ksh, możesz zebrać dopasowania do tablicy;

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

Twoje egrepwyrażenie regularne będzie pasowało tylko do katalogów z kropką ; Założyłem, że to pomyłka.

Oneiros Aug 21 2020 at 14:03

drukowanie res.stdoutpokaże, że zawiera znak końca linii.

>>>res.stdout
'0\n'

więc po prostu usuń znak „\ n”:

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

Alternatywnie, po prostu rzuć to jako liczbę całkowitą:

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