Cómo eliminar un directorio automáticamente cuando se mata un ejecutable

9

Muy a menudo, ejecutamos un ejecutable que necesita escribir / leer algunos archivos temporales. Por lo general, creamos un directorio temporal, ejecutamos el ejecutable allí y eliminamos el directorio cuando finaliza el script.

Quiero eliminar el directorio incluso si se mata el ejecutable. Traté de envolverlo en:

#!/bin/bash
dir=$(mktemp -d /tmp/foo.XXXXXXX) && cd $dir && rm -rf $dir
/usr/local/bin/my_binary

Cuando my_binarymuere, el último proceso del núcleo eliminará el directorio, ya que el script es el último proceso que lo contiene inode; pero no puedo crear ningún archivo en el directorio eliminado.

#!/bin/bash
dir=$(mktemp -d /tmp/foo.XXXXXXX) && cd $dir && rm -rf $dir
touch file.txt

salidas touch: file.txt: No such file or directory

Lo mejor que se me ocurre es eliminar el directorio temporal cuando el proceso muere, capturar las señales más comunes y ejecutar un proceso de limpieza con cron:

#!/bin/bash
dir=$(mktemp -d /tmp/d.XXXXXX) && cd "$dir" || exit 99
trap 'rm -rf "$dir"' EXIT
/usr/local/bin/my_binary

¿Hay alguna manera simple de crear un directorio realmente temporal que se elimine automáticamente cuando el binario actual muere, sin importar qué?

Joaquin Cuenca Abela
fuente
1
tenga en cuenta que tiene una pequeña ventana donde cleanupse puede ejecutar antes de que se realice el mktemp. Es posible que desee unset dirantes de establecer la trampa.
Stéphane Chazelas
Buena captura, actualicé el script para manejar esto y manejar un error en mktemp.
Joaquín Cuenca Abela
Pensé que la salida era obligatoria. Fijo.
Joaquín Cuenca Abela
Su último ejemplo menciona cron, pero no tiene nada que ver con cron. Ese último ejemplo también es el más seguro. Lo único que no manejará es SIGKILL.
Patrick
No incluí el script cron que estoy ejecutando para mantenerlo sucinto. Es un hallazgo sobre ese patrón para que coincida con directorios de más de 1 hora y rm. Quiero saber si hay alguna solución que también cubra el caso sigkill, o incluso un cierre brutal en el medio del guión.
Joaquín Cuenca Abela

Respuestas:

3

Su último ejemplo es el más seguro.

trap 'rm -rf "$dir"' EXIT

Esto se ejecutará mientras el shell en sí mismo siga siendo funcional. Básicamente, SIGKILL es lo único que no manejará ya que el shell se termina por la fuerza.
(quizás SIGSEGV también, no lo intenté, pero se puede atrapar)

Si no deja que el shell se limpie después de sí mismo, la única otra alternativa posible es que el núcleo lo haga. Esto normalmente no es una característica del núcleo, sin embargo, hay un truco que puede hacer, pero tiene sus propios problemas:

#!/bin/bash
mkdir /tmp/$$
mount -t tmpfs none /tmp/$$
cd /tmp/$$
umount -l /tmp/$$
rmdir /tmp/$$

do_stuff

Básicamente, crea un montaje tmpfs y luego lo desmonta perezosamente. Una vez que el guión esté terminado, se eliminará.
La desventaja, aparte de ser demasiado complejo, es que si el script muere por alguna razón antes del desmontaje, no tienes una montura por ahí.
Esto también usa tmpfs, que consumirá memoria. Pero podría hacer que el proceso sea más complejo y usar un sistema de archivos de bucle, y eliminar el archivo que lo respalda después de que esté montado.


En última instancia, lo trapmejor es en lo que respecta a la simplicidad y la seguridad, y a menos que su script se vuelva SIGKILL regularmente, me quedaría con él.

Patricio
fuente
¿Importa si la trampa se coloca antes mktempo después? Creo que si la trampa se coloca justo antes de la mktemp, incluso si la señal de salida se recibió después de la trampa y antes de la mktemp, todo lo que sucedería es rm -rfque se ejecutaría un comando con un argumento vacío, sin lograr nada. Pero si la trampa fuera después de la mktemp, podría haber una pequeña ventana de posibilidad de que el directorio temporal se quedara. ¿O estoy completamente fuera de la base?
Comodín el
1

Podrías usar el sistema de espera incorporado para esperar a que termine un trabajo en segundo plano:

blah &
wait
rm -rf $DIR
Matthew Cline
fuente
Pero eso será equivalente a blah; rm -rf $DIR, ¿verdad? Tiene el problema de que perderá $ DIR si se elimina el script.
Joaquín Cuenca Abela
Si el script secundario se elimina, el script primario seguirá existiendo para limpiarlo después. Si el script principal también se elimina, entonces sí, el directorio se quedará atrás.
Matthew Cline