2010-03-02 23 views
7

Aquí hay uno para los asistentes de bash-fu. No, en realidad, solo estoy bromeando, probablemente todos sepan esto excepto yo ...Creación de scripts Bash, comprobación de errores, registro

Estoy intentando crear un script de shell de respaldo. La idea es bastante simple: encontrar archivos en una carpeta determinada, anteriores a 7 días, tar/gzip a otro directorio y eliminarlos. El problema es que no estoy seguro de si tendré suficientes permisos para crear un archivo tar/gzip en el directorio de destino. ¿Hay alguna forma (correcta) de verificar si el archivo se ha creado correctamente y, de ser así, eliminar los archivos? De lo contrario, omita esa parte y no destruya los datos de los clientes. Escuché que no les gusta mucho eso.

Esto es lo que tengo hasta ahora:

01: #!/bin/bash 
02: 
03: ROOTDIR="/data/www" 
04: 
05: TAR="${ROOTDIR}/log/svg_out_xml/export_out_ack_$(date +%Y-%m-%d).tar" 
06: cd ${ROOTDIR}/exchange/export/out_ack/ 
07: find . -mtime +7 -type f -print0 | xargs -0 tar -cf "${TAR}" 
08: gzip ${TAR} 
09: find . -mtime +7 -type f -print0 | xargs -0 rm -f 

Básicamente, que había necesidad de comprobar si todo ha ido bien en las líneas 7 y 8, y si es así ejecutar 9.

Adicionalmente, I' Me gusta hacer un archivo de registro de estas operaciones, así que sé que todo salió bien (este es un trabajo cron nocturno).

+1

Aquí vienen todos los comentarios, use algo prefabricado es seguro. – Recursion

+0

Hablando de la experiencia, Recursion? :) –

+0

Tu etiqueta dice "bash", pero tu shebang dice "sh". –

Respuesta

6

Para el registro, se puede envolver secciones de la secuencia de comandos entre llaves y redirigir la salida estándar a un archivo de registro:

{ 
    script_command_1 
    script_command_2 
    script_command_3 
} >> /path/to/log_file 
+0

Kewl, espero que funcione si lo escribo así: '} >> $ {LOG} 2> & 1' –

+0

@dr: Sí, lo hará. –

5

El camino más fácil, pero con ningún mensaje de error explícito añadir a -e el tinglado, es decir #!/bin/sh -e lo que hará que la cáscara para salir si falla un comando ..

Cron le debe dar un mensaje de error a través del correo Supongo sin embargo.

Sin embargo, si desea hacer un esquema completo de copia de seguridad, le sugiero que use algo que ya se ha hecho. Hay muchos por ahí, y la mayoría funcionan muy bien.

+0

Excelente sugerencia. Siempre uso '-e' en mis scripts. –

+0

Gracias por la sugerencia, ¡muy útil! Desafortunadamente, cron no nos enviará nada ya que no somos los administradores de este sistema. Sin embargo, sería bueno ... –

+0

@dr: Lo hará si define MAILTO en su crontab. – falstro

3

GNU tar tiene --remove-files que eliminará los archivos una vez que se hayan agregado al archivo. v hará que enumere los archivos a medida que los agrega. z canalizará el alquitrán a través de gzip sobre la marcha.

Su solución find es atrevida; un archivo puede ajustarse al criterio entre invocaciones, por lo que se elimina pero no se realiza una copia de seguridad.

+0

Gracias por su respuesta. Es muy poco probable que un archivo encaje entre invocaciones, ya que este script se ejecutará a las 4AM cuando no se deben crear archivos en la carpeta de la que estoy haciendo una copia de seguridad. Por supuesto, siempre hay un usuario ... –

11

Para el registro, puede organizar para toda la salida escrita en la salida estándar y/o estándar error para ir a un archivo. De esta manera, no es necesario volver a dirigir la salida de cada comando:

# Save standard output and standard error 
exec 3>&1 4>&2 
# Redirect standard output to a log file 
exec 1>/tmp/stdout.log 
# Redirect standard error to a log file 
exec 2>/tmp/stderr.log 

# Now the output of all commands goes to the log files 
echo "This goes to /tmp/stdout.log" 
echo "This goes to /tmp/stderr.log" 1>&2 
... 

# Print a message to the original standard output (e.g. terminal) 
echo "This goes to the original stdout" 1>&3 

# Restore original stdout/stderr 
exec 1>&3 2>&4 
# Close the unused descriptors 
exec 3>&- 4>&- 

# Now the output of all commands goes to the original standard output & error 
... 

para ejecutar un comando sólo si uno anterior tiene éxito, se les puede encadenar con los condicionales:

# Execute command2 only if command1 succeeds, and command3 only if both succeed: 
command1 && command2 && command3 

# Execute command2 only if command1 fails 
command1 || command2 

por lo que puede hacer cosas como

{ find . -mtime +7 -type f -print0 | xargs -0 tar -cf "${TAR}" && 
    gzip ${TAR} && 
    find . -mtime +7 -type f -print0 | xargs -0 rm -f } || 
    { echo "Something failed" 1>&2; exit 1 } 

o facilitar los detalles en la salida del registro:

find . -mtime +7 -type f -print0 | xargs -0 tar -cf "${TAR}" || 
    { echo "find failed!!" 1>&2; exit 1 } 
gzip ${TAR} || 
    { echo "gzip failed!!" 1>&2; exit 1 } 
find . -mtime +7 -type f -print0 | xargs -0 rm -f || 
    { echo "cleanup failed!!" 1>&2; exit 1} 
+0

+1, ¡información increíble! –

+0

'1>' está implícito en '>' –

+3

pero 1> es más claro. – Idelic

Cuestiones relacionadas