linux - temporales - win setup files borrar
Eliminando archivos temp creados en una salida de salida inesperada (7)
Estoy creando archivos temporales de un script bash. Los borro al final del proceso, pero dado que el script se está ejecutando durante bastante tiempo, si lo elimino o simplemente CTRL-C durante la ejecución, los archivos temporales no se eliminan.
¿Hay alguna manera de detectar estos eventos y limpiar los archivos antes de que termine la ejecución?
Además, ¿existe algún tipo de práctica recomendada para el nombre y la ubicación de esos archivos temporales?
Actualmente no estoy seguro de si estoy usando:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
y
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
¿O tal vez hay algunas mejores soluciones?
Desea utilizar el comando trap para gestionar la salida del script o señales como CTRL-C. Consulte la Guía avanzada de scripts de Bash para obtener más información.
Para sus archivos temporales, usar el basename $0
es una buena idea, así como proporcionar una plantilla que proporcione espacio para suficientes archivos temporales:
tempfile() {
tempprefix=$(basename "$0")
mktemp /tmp/${tempprefix}.XXXXXX
}
TMP1=$(tempfile)
TMP2=$(tempfile)
trap ''rm -f $TMP1 $TMP2'' EXIT
La alternativa de usar un nombre de archivo predecible con $$ es un agujero de seguridad enorme y nunca, nunca, jamás pienses en usarlo. Incluso si se trata de un simple script personal en tu PC de usuario único. Es un mal hábito que no debes obtener. BugTraq está lleno de incidentes de "archivos temporales inseguros". Consulte here , here y here para obtener más información sobre el aspecto de seguridad de los archivos temporales.
Inicialmente estaba pensando en citar las inseguras asignaciones de TMP1 y TMP2, pero pensándolo bien probablemente no sería una buena idea .
No tiene que molestarse en eliminar esos archivos tmp creados con mktemp. Serán eliminados de todos modos más tarde.
Use mktemp si puede, ya que genera más archivos únicos y luego el prefijo ''$$''. Y parece más una forma de plataforma cruzada para crear archivos temporales y luego ponerlos explícitamente en / tmp.
Por lo general, creo un directorio en el que colocar todos mis archivos temporales, e inmediatamente después, creo un controlador EXIT para limpiar este directorio cuando el script se cierra.
MYTMPDIR=$(mktemp -d)
trap "rm -rf $MYTMPDIR" EXIT
Si coloca todos sus archivos temporales en $MYTMPDIR
, se borrarán cuando su script salga en la mayoría de los casos. Matar un proceso con SIGKILL (kill -9) mata el proceso de inmediato, por lo que su controlador EXIT no se ejecutará en ese caso.
Prefiero usar tempfile
que crea un archivo en / tmp de manera segura y no tiene que preocuparse por su nombre:
tmp=$(tempfile -s "your_sufix")
trap "rm -f ''$tmp''" exit
Puede configurar una " trap " para ejecutar al salir o en un control-c para limpiar.
trap "{ rm -f $LOCKFILE; }" EXIT
Alternativamente, uno de mis unix-isms favoritos es abrir un archivo, y luego eliminarlo mientras todavía lo tienes abierto. El archivo permanece en el sistema de archivos y usted puede leerlo y escribirlo, pero tan pronto como su programa finalice, el archivo desaparecerá. Sin embargo, no estoy seguro de cómo harías eso en bash.
Por cierto: un argumento que voy a dar a favor de mktemp en lugar de usar tu propia solución: si el usuario anticipa que tu programa va a crear enormes archivos temporales, podría querer configurar TMPDIR
en algún lugar más grande, como / var / tmp. mktemp reconoce que su solución enrollada a mano (segunda opción) no lo hace. Frecuentemente uso TMPDIR=/var/tmp gvim -d foo bar
, por ejemplo.
Solo tenga en cuenta que la respuesta elegida es bashism
, que significa solución como
trap "{ rm -f $LOCKFILE }" EXIT
funcionaría solo en bash (no captará Ctrl + c si shell es dash
o classic sh
), pero si quieres compatibilidad, entonces todavía necesitas enumerar todas las señales que quieras atrapar.
También tenga en cuenta que cuando el script sale de la trampa, la señal "0" (también conocida como EXIT) siempre se ejecuta y se obtiene una doble ejecución del comando trap
.
Esa es la razón para no apilar todas las señales en una línea si hay señal de SALIDA.
Para comprender mejor, observe el siguiente script que funcionará en diferentes sistemas sin cambios:
#!/bin/sh
on_exit() {
echo ''Cleaning up...(remove tmp files, etc)''
}
on_preExit() {
echo
echo ''Exiting...'' # Runs just before actual exit,
# shell will execute EXIT(0) after finishing this function
# that we hook also in on_exit function
exit 2
}
trap on_exit EXIT # EXIT = 0
trap on_preExit HUP INT QUIT TERM STOP PWR # 1 2 3 15 30
sleep 3 # some actual code...
exit
Esta solución le dará más control ya que puede ejecutar parte de su código en la aparición de señal real justo antes de la salida final (función preExit
) y si es necesario puede ejecutar algún código en la señal de SALIDA real (etapa final de salida)