¿Cómo eliminar de forma fiable todos los archivos temporales creados en un script?

0

¿Es posible atrapar la salida / retorno de una función? Para un programa que podría hacer

trap -- "clean_this" EXIT

Eso ejecutaría la función. clean_this cuando el programa sale. Me gustaría hacer algo por el estilo al salir de una función.

function myfunc() {
  echo "I'm a function"
}

myfunc &
wait $!

Ejecuto la función en un subshell, y me gustaría atrapar su salida / retorno. ¿Es eso posible?


EDITAR1

Aquí está mi propósito

Tengo un script para administrar los archivos temporales:

cat tempfiles.sh

## List of temp files
tmp_tmp_files=()

## Adds a file to the list of temp files
function tmp_add_file() {
  tmp_tmp_files+=("$1")
}

## Resets the list of temp files
function tmp_reset_files() {
  tmp_tmp_files=()
}

## Removes the list of temp files 
function tmp_rm_all() {
  rm -f "${tmp_tmp_files[@]}"
}

## Removes all temp files on exit and sigint
trap "tmp_rm_all" EXIT SIGINT

Aquí está mi guión principal:

cat mscript.sh

source tempfiles.sh

## ## Creates a temp file and writes in it
mfunc() {
  local tempfile=$(mktemp)
  tmp_add_file $tempfile
  echo "something" >> $tempfile
  echo "($BASHPID) - tempfiles: ${tmp_tmp_files[@]}"
}

## Creates a temp file in main shell
mfunc

## Creates a temp file in a subshell
(mfunc)

Llamo al guión principal:

$ bash mscript.sh 
(92250) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj
(92254) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq

Reviso los archivos temporales:

$ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj
cat: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj: No such file or directory

$ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq 
something

Los archivos temporales declarados en el subshell se pierden de la lista al salir del programa. Me gustaría tenerlos eliminados idealmente al final de la función. O tengo que eliminarlos específicamente antes de abandonar la función, es fácil y me cuesta una línea más:

mfunc() {
  local tempfile=$(mktemp)
  tmp_add_file $tempfile1
  echo "something" >> $tempfile
  echo "tempfiles: ${tmp_tmp_files[@]}"
  ## Process things...
  rm $tempfile1
}

Pero me gustaría saber si hay una manera elegante de tenerlos (los archivos temporales creados en el subshells ) eliminado automáticamente, como hago con trap s al salir del programa.

Entonces mi pregunta es: ¿es posible hacerlo? ¿Cuáles podrían ser algunas alternativas?

kaligne
fuente
¿Qué estás intentando lograr? La función puesta en segundo plano puede llamar a otra función, así que vamos a myfunc llamada clean_this al final. O invocarlos como { myfunc ; clean_this ; } &. ¿Realmente necesitas una trampa?
Kamil Maciorowski
Gracias por responder. Aquí edité mi pregunta y escribí mi propósito. Bueno, seguramente puedo evitar las trampas, pero desde que comencé a usarlas, si puedo hacer lo que quiero de una manera fácil ... ¿Por qué no?
kaligne

Respuestas:

1

Las subshells heredan el entorno o parte de él. Parece que cuando ejecutas una función en un subshell, no necesitas exportar tus variables (compara: No es necesario exportar cuando se ejecutan funciones en subshell ). Puede haber algunos casos en los que necesite export Pero concentrémonos en tu ejemplo.

Su enfoque es defectuoso y será difícil de mantener porque la herencia va en un sentido. Cada (mfunc) hereda tmp_tmp_files Y trabaja con su propia copia de la matriz. No hay forma de que pueda modificar el original. tmp_tmp_files utilizado en el guión principal. Por lo tanto, el script principal no puede limpiar todo, simplemente no posee suficiente información.

Si elige limpiar de la función subshelled, deberá prestar atención y diferenciar los archivos temporales de la función de los archivos temporales del script principal. La eliminación prematura de este último puede hacer que su script falle.

Enfoque alternativo: un directorio temporal.

  1. En lugar de crear una matriz, cree un directorio y recuerde su ruta. Hazlo una vez en el principio y export si necesitas:

    tempdir=$(mktemp -d mscript.XXXXXXXXXX)
    
  2. Crea cada archivo temporal dentro del directorio temporal, como este:

    tempfile=$(mktemp -p "$tempdir")
    
  3. Al final, elimine todo el directorio, sin importar si los archivos en particular fueron creados por el script principal o por un subshell, o incluso por algún programa externo de terceros. Puedes usar una trampa para realizar este paso. Simplemente:

    rm -r "$tempdir"
    
Kamil Maciorowski
fuente
gracias eso es lo que hago por ahora Entonces, entiendo que no hay manera de disparar nada tan pronto como una función se detiene. ¿Derecha?
kaligne
@ user3298319 No lo sé seguro. Sucedió que tu pregunta era la Problema XY Y respondí para resolver tu problema real. También cambié el título, por lo que ahora no es útil para los usuarios interesados ​​en las trampas; Es útil en el tema de archivos temporales. Mi punto es: esta pregunta ha evolucionado. Si desea investigar las trampas, puede hacer otra pregunta y explicar que está preguntando por curiosidad. Sin embargo, esto puede no ser bien recibido. El sitio se concentra en resolver problemas prácticos y los usuarios tienden a entregarle las herramientas adecuadas como yo lo hice.
Kamil Maciorowski