Escribir condicionales de Python para crontab

Aug 21 2020

¿Cómo funciona una declaración if de Python al editarla en crontab? Usando Python 3.6.3

Usando linux crontab estoy tratando de obtener un recuento de la cantidad de archivos ocultos dentro de un directorio (que no sean los directorios "." Y "..") para poder programar una alerta. Lo siguiente obtiene la cantidad en formato de cadena:

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)

Entonces quiero algo como

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

Se agradece cualquier ayuda.

Respuestas

1 tripleee Aug 21 2020 at 14:43

Una solución mucho mejor es evitar un subproceso por completo. (E incluso si usa un subproceso, no lo use lsen scripts).

from pathlib import Path

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

En realidad, no es necesario comprobar la longitud; puedes decir

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

De manera algo oscura, pero más sucinta, podría iterar sobre el generador en su lugar; el cuerpo del bucle se ejecutará solo si hay al menos un archivo que coincida. Esta es una optimización si solo le importa si hay al menos un archivo, ya que se detiene una vez que encuentra el primero;

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

A Python no le importa si ejecuta su script desde crono no (aunque a veces necesita organizar el entorno para Python en su crontrabajo si tiene bibliotecas instaladas en ubicaciones no estándar). Pero, ¿por qué está usando Python aquí si toda su lógica de negocios está en scripts de shell? (Aunque sus secuencias de comandos de shell también podrían beneficiarse al estudiar algunos antipatrones para evitar).

Aquí está todo el asunto completamente en un script de shell, usando una lógica similar:

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

Bash ofrece shopt -s nullglobevitar entrar en el bucle si el comodín no coincide; pero se cronejecuta shy no es del todo difícil evitar los bashismos aquí (aunque el comportamiento global en el caso de que no haya coincidencias es sorprendente).

Si desea todas las coincidencias en un script de shell, puede decir

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

Si usa Bash o ksh, puede recopilar las coincidencias en una 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

Su egrepexpresión regular solo coincidiría en directorios de puntos ; Supuse que esto fue un error.

Oneiros Aug 21 2020 at 14:03

la impresión res.stdoutle mostrará que tiene un carácter de línea final dentro de él.

>>>res.stdout
'0\n'

así que solo quita el carácter '\ n':

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

Alternativamente, simplemente conviértalo como un número entero:

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