Estoy creando archivos temporales a partir de un script bash. Los estoy eliminando al final del procesamiento, pero dado que el script se está ejecutando durante bastante tiempo, si lo mato o simplemente CTRL-C durante la ejecución, los archivos temporales no se eliminan.
¿Hay alguna forma de detectar esos eventos y limpiar los archivos antes de que finalice 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 entre usar:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
y
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
¿O tal vez hay mejores soluciones?
bash
exit
temporary-files
skinp
fuente
fuente
Respuestas:
Puede establecer una " trampa " para ejecutar al salir o en un control-c para limpiar.
Alternativamente, uno de mis unix-isms favoritos es abrir un archivo y luego eliminarlo mientras aún lo tienes abierto. El archivo permanece en el sistema de archivos y puede leerlo y escribirlo, pero tan pronto como se cierre el programa, el archivo desaparecerá. Sin embargo, no estoy seguro de cómo harías eso en bash.
Por cierto: un argumento que daré a favor de mktemp en lugar de usar su propia solución: si el usuario anticipa que su programa va a crear archivos temporales enormes, es posible que desee configurarlo
TMPDIR
en un lugar más grande, como / var / tmp. mktemp reconoce eso, su solución hecha a mano (segunda opción) no lo hace. Yo uso con frecuenciaTMPDIR=/var/tmp gvim -d foo bar
, por ejemplo.fuente
exec 5<>$TMPFILE
descriptor de archivo lazos 5 a $ TMPFILE como lectura y escritura, y se puede utilizar<&5
,>&5
y/proc/$$/fd/5
(Linux) a partir de entonces. El único problema es que Bash carece deseek
función ...trap
: no hay forma de atraparSIGKILL
(por diseño, ya que termina inmediatamente la ejecución). Entonces, si eso pudiera suceder, tenga un plan alternativo (comotmpreaper
). En segundo lugar, las trampas no son acumulativas: si tiene más de una acción que realizar, todas deben estar en eltrap
comando. Una forma de hacer frente a múltiples acciones de limpieza es definir una función (y se puede redefinir como los fondos de su programa, si es necesario) y la referencia que:trap cleanup_function EXIT
.trap "rm -f $LOCKFILE" EXIT
o obtendría un final inesperado de error de archivo.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 sale el script.
Si coloca todos sus archivos temporales debajo
$MYTMPDIR
, todos se eliminarán cuando su secuencia de comandos salga en la mayoría de las circunstancias. Sin embargo, matar un proceso con SIGKILL (kill -9) mata el proceso de inmediato, por lo que su controlador EXIT no se ejecutará en ese caso.fuente
Desea utilizar el comando trap para manejar la salida del script o señales como CTRL-C. Consulte la Wiki de Greg para obtener más detalles.
Para sus archivos temporales, usar
basename $0
es una buena idea, además de proporcionar una plantilla que proporcione espacio para suficientes archivos temporales:fuente
$()
. También se agregaron las comillas dobles.tempfile
comando, mientras que todos los sistemas modernos razonables que conozco tienen unmktemp
comando.Solo tenga en cuenta que la respuesta elegida es
bashism
, lo que significa solución comofuncionaría solo en bash (no detectará Ctrl + c si shell es
dash
o clásicosh
), pero si desea compatibilidad, aún debe enumerar todas las señales que desea atrapar.También tenga en cuenta que cuando el script sale de la trampa para la señal "0" (también conocido como EXIT) siempre se realiza, lo que resulta en una doble ejecución del
trap
comando.Esa es la razón para no apilar todas las señales en una línea si hay una señal de SALIDA.
Para comprenderlo mejor, consulte el siguiente script que funcionará en diferentes sistemas sin cambios:
Esta solución le dará más control, ya que puede ejecutar parte de su código en la aparición de la señal real justo antes de la salida final (
preExit
función) y, si es necesario, puede ejecutar algún código en la señal de SALIDA real (etapa final de salida)fuente
La alternativa de usar un nombre de archivo predecible con $$ es un enorme agujero de seguridad y nunca, nunca, nunca debería pensar en usarlo. Incluso si es solo un simple script personal en su PC de un solo usuario. Es un hábito muy malo que no debes adquirir. BugTraq está lleno de incidentes de "archivos temporales inseguros". Consulte aquí , aquí y aquí para obtener más información sobre el aspecto de seguridad de los archivos temporales.
Inicialmente estaba pensando en citar las asignaciones inseguras de TMP1 y TMP2, pero pensándolo bien, probablemente no sería una buena idea .
fuente
Prefiero usar
tempfile
que crea un archivo en / tmp de manera segura y no tiene que preocuparse por su nombre:fuente
No puedo creer que tanta gente asuma que un nombre de archivo no contendrá un espacio. El mundo se colapsará si $ TMPDIR se asigna alguna vez al "directorio temporal".
Los espacios y otros caracteres especiales como comillas simples y retornos de carro en los nombres de archivos deben considerarse en el código como un requisito de un hábito de programación decente.
fuente
trap 'rm -f "${zTemp}"' EXIT
manejan correctamente los espacios y otros caracteres especiales, la solución de esta respuesta no difiere la evaluación dezTemp
. Por lo tanto, no hay necesidad de preocuparse por el valor dezTemp
ser modificado más adelante en el guión. Además,zTemp
se puede declarar local a una función; no necesita ser una variable de secuencia de comandos global.${parameter@operator}
expansiones se agregaron en Bash 4.4 (publicado en septiembre de 2016).No tiene que molestarse en eliminar esos archivos tmp creados con mktemp. De todos modos, se eliminarán más tarde.
Use mktemp si puede, ya que genera más archivos únicos que el prefijo '$$'. Y parece una forma más multiplataforma de crear archivos temporales y luego ponerlos explícitamente en / tmp.
fuente