Escrevendo condicionais de python para crontab

Aug 21 2020

Como funciona uma instrução if do python ao editá-la no crontab? Usando python 3.6.3

Usando o crontab do linux, estou tentando obter uma contagem da quantidade de arquivos ocultos em um diretório (além dos diretórios "." E "..") para poder agendar um alerta. O seguinte obtém o valor em formato de string:

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)

Então eu quero algo como

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

Qualquer ajuda é apreciada.

Respostas

1 tripleee Aug 21 2020 at 14:43

Uma solução muito melhor é evitar totalmente um subprocesso. (E mesmo se você usar um subprocesso, não use lsem scripts.)

from pathlib import Path

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

Na verdade, não há necessidade real de verificar o comprimento; Você pode dizer

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

De forma um tanto obscura, mas mais sucinta, você pode iterar no gerador; o corpo do loop será executado apenas se houver pelo menos um arquivo que corresponda. Esta é uma otimização se você só se importa se há pelo menos um arquivo, pois ela para quando encontra o primeiro;

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

Python não se importa se você executa seu script cronou não (embora às vezes você precise organizar o ambiente para Python em seu crontrabalho se você tiver bibliotecas instaladas em locais não padrão). Mas por que você está usando Python aqui se toda a sua lógica de negócios está em scripts de shell? (Embora seu script de shell também possa se beneficiar do estudo de alguns antipadrões para evitar.)

Aqui está tudo em script de shell, usando lógica semelhante:

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

O Bash oferece shopt -s nullglobevitar entrar no loop se o curinga não tiver correspondência; mas croné executado she não é totalmente difícil evitar bashisms aqui (embora o comportamento globbing no caso de nenhuma correspondência seja surpreendente).

Se você quiser todas as correspondências em um script de shell, pode dizer

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

Se você usar Bash ou ksh, poderá coletar as correspondências em uma matriz;

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

Sua egrepregex só corresponderia a diretórios de ponto ; Presumi que isso foi um erro.

Oneiros Aug 21 2020 at 14:03

a impressão res.stdoutmostrará que há um caractere de linha final dentro dele.

>>>res.stdout
'0\n'

então apenas retire o caractere '\ n':

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

Como alternativa, basta convertê-lo como um inteiro:

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