Je crée des fichiers temporaires à partir d'un script bash. Je les supprime à la fin du traitement, mais comme le script est en cours d'exécution 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 d'attraper ces événements et de nettoyer les fichiers avant la fin de l'exécution?
Existe-t-il également une sorte de meilleure pratique pour la dénomination et l'emplacement de ces fichiers temporaires?
Je ne suis actuellement pas sûr d'utiliser:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
et
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
Ou peut-être y a-t-il de meilleures solutions?
bash
exit
temporary-files
skinp
la source
la source
Réponses:
Vous pouvez définir un « piège » à exécuter à la sortie ou sur un contrôle-c pour nettoyer.
Alternativement, l'un de mes unix-ismes préférés est d'ouvrir un fichier, puis de le supprimer pendant que vous l'avez encore 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 termine, 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 un
TMPDIR
emplacement 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équemmentTMPDIR=/var/tmp gvim -d foo bar
, par exemple.la source
exec 5<>$TMPFILE
descripteur de fichier liens 5 à $ TMPFILE en lecture-écriture, et vous pouvez utiliser<&5
,>&5
et/proc/$$/fd/5
(Linux) par la suite. Le seul problème est que Bash manque deseek
fonction ...trap
: il n'y a aucun moyen de piégerSIGKILL
(par conception, car cela met immédiatement fin à l'exécution). Donc, si cela peut arriver, ayez un plan de secours (tel quetmpreaper
). Deuxièmement, les interruptions ne sont pas cumulatives - si vous avez plus d'une action à effectuer, elles doivent toutes figurer dans latrap
commande. Une façon de faire face à de multiples actions de nettoyage est de définir une fonction (et vous pouvez le redéfinir comme produit de votre programme, le cas échéant) et référence:trap cleanup_function EXIT
.trap "rm -f $LOCKFILE" EXIT
ou j'obtiendrais une erreur de fin de fichier inattendue.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 lorsque le script se termine.
Si vous placez tous vos fichiers temporaires sous
$MYTMPDIR
, ils seront tous supprimés à la fin de votre script dans la plupart des cas. Tuer un processus avec SIGKILL (kill -9) tue le processus tout de suite, donc votre gestionnaire EXIT ne fonctionnera pas dans ce cas.la source
Vous souhaitez utiliser la commande trap pour gérer la sortie du script ou des signaux tels que CTRL-C. Consultez le Wiki de Greg pour plus de détails.
Pour vos
basename $0
fichiers temporaires , utiliser est une bonne idée, ainsi que fournir un modèle qui offre suffisamment de place pour les fichiers temporaires:la source
$()
. Ajout des guillemets doubles également.tempfile
commande, alors que tous les systèmes modernes raisonnables que je connais ont unemktemp
commande.Gardez simplement à l'esprit que la réponse choisie est
bashism
, ce qui signifie solution commene fonctionnerait que dans bash (il n'attrapera pas Ctrl + c si shell est
dash
ou classiquesh
), mais si vous voulez la compatibilité, vous devez toujours énumérer tous les signaux que vous souhaitez intercepter.Gardez également à l'esprit que lorsque le script sort, le trap pour le signal "0" (aka EXIT) est toujours exécuté, ce qui entraîne une double exécution de la
trap
commande.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 changement:
Cette solution vous donnera plus de contrôle puisque vous pouvez exécuter une partie de votre code sur l'occurrence du signal réel juste avant la sortie finale (
preExit
fonction) et si nécessaire, vous pouvez exécuter du code au signal EXIT réel (étape finale de la sortie)la source
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 prendre. BugTraq est plein d'incidents de "fichiers temporaires non sécurisés". Voir ici , ici et ici pour plus d'informations sur l'aspect sécurité des fichiers temporaires.
Je pensais au départ citer les affectations non sécurisées TMP1 et TMP2, mais à la réflexion, ce ne serait probablement pas une bonne idée .
la source
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:la source
Je ne peux pas croire que tant de gens supposent qu'un nom de fichier ne contiendra pas d'espace. Le monde plantera si $ TMPDIR est assigné à un "répertoire temporaire".
Les espaces et autres caractères spéciaux comme les guillemets simples et les retours chariot dans les noms de fichiers doivent être considérés dans le code comme une exigence d'une habitude de programmation décente.
la source
trap 'rm -f "${zTemp}"' EXIT
gèrent correctement les espaces et autres caractères spéciaux, la solution de cette réponse ne reporte pas l'évaluation dezTemp
. Il n'y a donc pas lieu de s'inquiéter de la valeur d'zTemp
être modifié plus tard dans le script. En outre,zTemp
peut être déclaré local à une fonction; il n'a pas besoin d'être une variable de script globale.${parameter@operator}
extensions ont été ajoutées dans Bash 4.4 (publié en septembre 2016).Vous n'avez pas à vous soucier de supprimer les 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 plus de fichiers uniques que le préfixe «$$». Et cela ressemble à une manière plus multiplateforme de créer des fichiers temporaires, puis de les mettre explicitement dans / tmp.
la source