Je crée des fichiers temporaires à partir d'un script bash. Je les supprime à la fin du traitement, mais comme le script s'exécute depuis assez longtemps, si je le tue ou simplement CTRL-C pendant l'exécution, les fichiers temporaires ne sont pas supprimés.
Existe-t-il un moyen de détecter ces événements et de nettoyer les fichiers avant la fin de l'exécution?
En outre, existe-t-il une sorte de meilleure pratique pour la dénomination et l'emplacement de ces fichiers temporaires?
Je ne suis actuellement pas sûr entre l'utilisation de:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
et
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
Ou peut-être existe-t-il de meilleures solutions?
Vous pouvez définir un " trap " à exécuter à la sortie ou sur un contrôle-c pour nettoyer.
trap "{ rm -f $LOCKFILE; }" EXIT
Alternativement, l'un de mes unix-isms préférés consiste à ouvrir un fichier, puis à le supprimer pendant que vous l'avez toujours ouvert. Le fichier reste sur le système de fichiers et vous pouvez le lire et l'écrire, mais dès que votre programme se ferme, le fichier disparaît. Je ne sais pas comment vous feriez cela en bash, cependant.
BTW: Un argument que je donnerai en faveur de mktemp au lieu d'utiliser votre propre solution: si l'utilisateur prévoit que votre programme va créer d'énormes fichiers temporaires, il voudra peut-être définir TMPDIR
à un endroit plus grand, comme/var/tmp. mktemp reconnaît que votre solution roulée à la main (deuxième option) ne le fait pas. J'utilise fréquemment TMPDIR=/var/tmp gvim -d foo bar
, par exemple.
Je crée généralement un répertoire dans lequel placer tous mes fichiers temporaires, puis immédiatement après, crée un gestionnaire EXIT pour nettoyer ce répertoire à la fin du script.
MYTMPDIR=$(mktemp -d)
trap "rm -rf $MYTMPDIR" EXIT
Si vous placez tous vos fichiers temporaires sous $MYTMPDIR
, ils seront tous supprimés lorsque votre script se terminera dans la plupart des cas. Tuer un processus avec SIGKILL (kill -9) tue le processus tout de suite, donc votre gestionnaire EXIT ne s'exécutera pas dans ce cas.
Vous souhaitez utiliser la commande trap pour gérer la sortie du script ou des signaux comme CTRL-C. Voir le Wiki de Greg pour plus de détails.
Pour vos fichiers temporaires, utilisez basename $0
est une bonne idée, en plus de fournir un modèle qui offre suffisamment de place pour les fichiers temporaires:
tempfile() {
tempprefix=$(basename "$0")
mktemp /tmp/${tempprefix}.XXXXXX
}
TMP1=$(tempfile)
TMP2=$(tempfile)
trap 'rm -f $TMP1 $TMP2' EXIT
Gardez à l'esprit que la réponse choisie est bashism
, ce qui signifie que la solution
trap "{ rm -f $LOCKFILE }" EXIT
ne fonctionnerait qu'en bash (il n'attrapera pas Ctrl + c si Shell est dash
ou classique sh
), mais si vous voulez la compatibilité alors vous devez toujours énumérer tous les signaux que vous voulez intercepter .
Gardez également à l'esprit que lorsque le script se termine, le piège du signal "0" (aka EXIT) est toujours exécuté, ce qui entraîne une double exécution de la commande trap
.
C'est la raison pour ne pas empiler tous les signaux sur une seule ligne s'il y a un signal EXIT.
Pour mieux le comprendre, regardez le script suivant qui fonctionnera sur différents systèmes sans modifications:
#!/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 lors de l'occurrence du signal réel juste avant la sortie finale (fonction preExit
) et si nécessaire, vous pouvez exécuter du code au signal EXIT réel (dernière étape de sortie)
L'alternative d'utiliser un nom de fichier prévisible avec $$ est une faille de sécurité béante et vous ne devriez jamais, jamais, jamais penser à l'utiliser. Même s'il ne s'agit que d'un simple script personnel sur votre PC mono-utilisateur. C'est une très mauvaise habitude que vous ne devriez pas acquérir. BugTraq est plein d'incidents de "fichier temporaire non sécurisé". Voir ici , ici et ici pour plus d'informations sur l'aspect sécurité des fichiers temporaires.
Je pensais initialement à citer les affectations TMP1 et TMP2 non sécurisées, mais à la réflexion, cela serait probablement ce n'est pas une bonne idée .
Je préfère utiliser tempfile
qui crée un fichier dans/tmp de manière sûre et vous n'avez pas à vous soucier de son nom:
tmp=$(tempfile -s "your_sufix")
trap "rm -f '$tmp'" exit