Suppression des fichiers temporaires créés en sortie bash inattendue
-
22-08-2019 - |
Question
Je crée des fichiers temporaires à partir d'un script bash. Je les supprimer à la fin du traitement, mais étant donné que le script est en cours d'exécution pour un temps assez long, si je tue ou simplement CTRL-C lors de l'exécution, les fichiers temporaires ne sont pas supprimés.
Est-il possible que je peux attraper ces événements et le nettoyage des fichiers avant l'exécution se termine?
Aussi, est-il une sorte de meilleures pratiques pour la désignation et l'emplacement de ces fichiers temp?
Je suis actuellement pas sûr entre l'utilisation:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
et
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
Ou peut-être est-il des meilleures solutions?
La solution
Vous pouvez définir un « rel="noreferrer"> » à exécuter sur sortie ou sur une commande de c à nettoyer.
trap "{ rm -f $LOCKFILE; }" EXIT
Alternativement, l'un de mes favoris unix-ismes est d'ouvrir un fichier, puis supprimez-le pendant que vous avez encore ouvert. Le fichier reste sur le système de fichiers et vous pouvez lire et écrire, mais dès que votre programme se termine, le fichier disparaît. Je ne sais pas comment vous faites cela en bash, cependant.
BTW: Un argument que je vais vous donner en faveur de mktemp au lieu d'utiliser votre propre solution: si l'utilisateur attend votre programme va créer d'énormes fichiers temporaires, il pourrait vouloir mettre TMPDIR
à un endroit plus grand, comme / var / tmp . mktemp reconnaît que, votre solution roulées à la main (deuxième option) ne fonctionne pas. Je l'utilise souvent TMPDIR=/var/tmp gvim -d foo bar
, par exemple.
Autres conseils
Je crée généralement un répertoire dans lequel placer tous mes fichiers temporaires, puis immédiatement après, créer un gestionnaire EXIT pour nettoyer ce répertoire lors de la fermeture du script.
MYTMPDIR=$(mktemp -d)
trap "rm -rf $MYTMPDIR" EXIT
Si vous mettez tous vos fichiers temporaires sous $MYTMPDIR
, ils seront tous supprimés lors de votre script dans la sortie de la plupart des cas. Tuer un processus avec SIGKILL (kill -9) tue le processus tout de suite, donc votre gestionnaire EXIT ne fonctionne pas dans ce cas.
Vous voulez utiliser le piège la commande pour gérer la sortie du script ou des signaux comme CTRL-C. Voir Wiki Greg pour plus de détails.
Pour vos fichiers temporaires, en utilisant basename $0
est une bonne idée, ainsi que de fournir un modèle qui offre de la place pour les fichiers assez temp:
tempfile() {
tempprefix=$(basename "$0")
mktemp /tmp/${tempprefix}.XXXXXX
}
TMP1=$(tempfile)
TMP2=$(tempfile)
trap 'rm -f $TMP1 $TMP2' EXIT
Il suffit de garder à l'esprit que CHOISI réponse est bashism
, ce qui signifie que la solution
trap "{ rm -f $LOCKFILE }" EXIT
ne fonctionnerait que dans bash (il ne sera pas attraper Ctrl + c si shell est dash
ou sh
classique), mais si vous voulez la compatibilité alors vous avez encore besoin d'énumérer tous les signaux que vous voulez piéger.
Gardez à l'esprit que quand le script sort du piège pour le signal « 0 » (aka EXIT) est toujours réalisée résultant en double exécution de commande trap
.
Que la raison de ne pas empiler tous les signaux dans une ligne si le signal est EXIT.
Pour mieux comprendre regardez le script suivant qui fonctionnera à travers différents systèmes sans changement:
#!/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
Cette solution vous donnera plus de contrôle puisque vous pouvez exécuter une partie de votre code sur la présence de signal réel juste avant la sortie finale (fonction preExit
) et si elle avait besoin, vous pouvez exécuter un code à signal EXIT réelle (dernière étape de sortie)
La possibilité d'utiliser un nom de fichier prévisible $$ est un trou béant de sécurité et vous ne devriez jamais, jamais, jamais pensé à l'utiliser. Même si elle est juste un simple script personnel sur votre PC utilisateur unique. Il est une très mauvaise habitude vous ne devriez pas obtenir. BugTraq est plein de "fichiers temporaires non sécurisés" incidents. Voir , ici et ici pour plus d'informations sur l'aspect de la sécurité des fichiers temporaires.
Je pensais d'abord de citer les missions de TMP1 et tmp2 non sécurisés, mais à la réflexion qui serait probablement ne pas être une bonne idée .
Je préfère utiliser tempfile
qui crée un fichier dans / tmp de la manière sûre et vous n'avez pas à vous soucier de sa dénomination:
tmp=$(tempfile -s "your_sufix")
trap "rm -f '$tmp'" exit
Vous ne devez pas déranger la suppression de ces fichiers tmp créés avec mktemp. Ils seront supprimés de toute façon plus tard.
Utilisez mktemp si vous le pouvez car il génère des fichiers plus uniques alors préfixe « $$ ». Et il ressemble beaucoup plus de plate-forme de croix pour créer des fichiers temporaires, puis les mettre explicitement dans / tmp.