* 13 * * * sh /Users/gentaliaru/Dropbox/work/scripts/backup.sh >/tmp/stdout.log 2>/tmp/stderr.log
Esta tarea cron comenzará a las 13:00 UTC y se ejecutará cada minuto . Según tu nota "suele tardar unos 5 minutos" cron está iniciando cada minuto un nuevo trabajo antes de que el último haya terminado. De hecho, es una especie de bucle.
La primera *
tiene que ser sustituido por 0
para iniciar el trabajo todos los días a las 13:00 horas sólo una vez:
0 13 * * * sh /Users/gentaliaru/Dropbox/work/scripts/backup.sh >/tmp/stdout.log 2>/tmp/stderr.log >/dev/null 2>&1
Aparte del tema del cron, vale la pena considerar los siguientes consejos. Muestra cómo mejorar la robustez y la notificación (incluso para los trabajos fallidos) para su trabajo cron.
Compruebe siempre primero los recursos (archivos, ruta, etc.)
Un escollo común con cron son los recursos perdidos (archivos o rutas) durante la ejecución de un trabajo.
Por lo tanto, un mejor enfoque es especificar siempre las rutas completas y realizar algunas comprobaciones si los archivos y directorios existen. Todo el script debería tener este aspecto para manejar adecuadamente las rutas y archivos existentes/no existentes:
#!/bin/sh
mntPoint="$(/usr/sbin/diskutil info /Volumes/X5/ | /usr/bin/grep 'Mount Point' | /usr/bin/tr -s ' ' | /usr/bin/cut -d ' ' -f 4)"
if [ $mntPoint != "/Volumes/X5" ]
then
/usr/bin/osascript -e 'display notification "/Volumes/X5 has not been mounted" with title "Cron job aborted"'
exit;
fi
[[ -f '/Volumes/X5/backup/git.tar.tz' ]] && /bin/rm -rf '/Volumes/X5/backup/git.tar.tz'
[[ ! -d '/Volumes/X5/backup' ]] && mkdir '/Volumes/X5/backup'
if /usr/bin/tar -czf /Volumes/X5/backup/git.tar.tz /Users/gentaliaru/ws/git/ 2> /Volumes/X5/backup/.tar.log
then
/usr/bin/osascript -e "display notification \"Backup written to /Volumes/X5/backup/git.tar.tz\" with title \"Cron job successfully completed\""
else
# do not use /usr/bin/read as the internal read command is required!
read errMsg < /Volumes/X5/backup/.tar.log
/usr/bin/osascript -e "display notification \"$errMsg\" with title \"Cron job failed\""
# /path/to/terminal-notifier -message "git Backup is complete" -title "Backup notifier"
fi
Explicación
En primer lugar recomiendo convertir el archivo ascii "plano" en un verdadero shell script añadiendo un shebang en la parte superior del archivo.
#!/bin/sh
Compruebe si la unidad de copia de seguridad está correctamente montada
Las líneas 3-8 aseguran que la unidad de respaldo está montada; de lo contrario, lanzan una notificación. Una comprobación con sólo [[ -d /Volumes/X5 ]]
no es lo suficientemente fiable, ya que a veces (muy raramente, pero ha sucedido) la ruta de montaje existe pero sin unidad adjunta. Comprobando con diskutil
sortear estas rarezas ocasionales.
Entonces, rm -rf /Volumes/X5/backup/git.tar.tz
sin comprobar la existencia del archivo es otra trampa. Es mejor comprobar primero la existencia:
[[ -f '/Volumes/X5/backup/git.tar.tz' ]] && /bin/rm -rf '/Volumes/X5/backup/git.tar.tz'
Además, tu script muestra dos rutas diferentes. El comando de eliminación rm
en la línea 1 se refiere a /Volumes/X5/backup
pero el tar
en la línea 2 se refiere a /Volumes/X5/tmp/git.tar.tz
. ¿Es esto realmente lo que quieres?
Invocando tar
para escribir un archivo en una ruta/subdirectorio inexistente arroja el siguiente error (al menos aquí en HighSierra 10.13.6):
tar: Failed to open '/Volumes/X5/backup/git.tar.tz'
Por lo tanto, compruebe primero la existencia de tar
y crearlo si no existe:
[[ ! -d '/Volumes/X5/backup' ]] && mkdir '/Volumes/X5/backup'
La línea 13 realiza finalmente la copia de seguridad y lanza -en caso de éxito- la notificación (línea 15). En caso contrario, se lanza una notificación sobre el fallo (línea 19).
Uso de recursos internos de MacOS para la notificación
Mi ejemplo utiliza recursos internos de MacOS sin necesidad de herramientas de terceros como terminal-notifier
. Se hace mediante una línea de AppleScript que es invocada por osascript
.
Si desea mantener la solución con terminal-notifier
sólo hay que sustituir las líneas (15 y 19) por osascript
) con lo siguiente:
/path/to/terminal-notifier -message "Backup written to /Volumes/X5/backup/git.tar.tz" -title "Cron job successfully completed" # Line 15
/path/to/terminal-notifier -message "${errMsg}" -title "Cron job failed" # Line 19
También es una buena práctica especificar la ruta completa para terminal-notifier
. En caso de que sea instalado por Homebrew utilizar algo como /usr/local/bin/terminal-notifier
.
Entonces hazlo ejecutable:
chmod u+x /Users/gentaliaru/Dropbox/work/scripts/backup.sh
Sidenode para Homebrew
Las rutas difieren entre las plataformas (consulte la documentación aquí ):
Su /usr/local
en MacOS Intel y /opt/homebrew
en Silicio de Apple