Réponses:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Vous pouvez vous assurer qu'un fichier est supprimé lorsque les scripts se terminent (y compris les tentatives de suppression et les crashs) en ouvrant un descripteur de fichier dans le fichier et en le supprimant. Le fichier reste disponible (pour le script; pas vraiment pour d'autres processus, mais /proc/$PID/fd/$FD
constitue une solution de contournement) tant que le descripteur de fichier est ouvert. Lorsqu'il est fermé (ce que fait automatiquement le noyau lorsque le processus se termine), le système de fichiers supprime le fichier.
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc
- sauf pour les systèmes qui ne l'ont pas.
exec 3> "$tmpfile"
fait? N'est-ce pas seulement utile si le fichier tmp est un script autonome?
cat <&3
va donner Bad file descriptor
. J'apprécierais si vous le répariez ou le retiriez; la désinformation n'aide pas beaucoup.
Utilisez mktemp
pour créer un fichier temporaire ou un répertoire:
temp_file=$(mktemp)
Ou pour un répertoire:
temp_dir=$(mktemp -d)
A la fin du script, vous devez supprimer le fichier / répertoire temporaire:
rm ${temp_file}
rm -R ${temp_dir}
mktemp crée un fichier dans le /tmp
répertoire ou dans le répertoire donné avec l' --tmpdir
argument.
trap "rm -f $temp_file" 0 2 3 15
immédiatement après la création du fichier, de sorte que ctrl-C
le fichier soit toujours supprimé lorsque le script se ferme ou s’arrête .
EXIT
c'est le seul crochet pour trap
?
kill -9 $somepid
. Ce signal de destruction est une mort imminente et il ne se passe rien d'autre.
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXIT
suffit.
Si vous utilisez un système qui contient mktemp , vous devriez l’utiliser comme autre réponse.
Avec les outils POSIX:
umask 0177
tmpfile=/tmp/"$0"."$$"."$(awk 'BEGIN {srand();printf "%d\n", rand() * 10^10}')"
trap 'rm -f -- "$tmpfile"' INT TERM HUP EXIT
: > "$tmpfile"
EXIT
est le seul crochet pour trap
?
tmpfile
reste supprimé avant la sortie du script, mais pas lorsque le script reçoit d'autres signaux.
That's not what happens
?
mktemp
provient de HP / UX avec une syntaxe différente. Todd C. Miller en a créé un différent pour OpenBSD au milieu des années 90 (copié par FreeBSD et NetBSD) et l'a ensuite rendu disponible en tant qu'utilitaire autonome (www.mktemp.org). C'est celui qui était généralement utilisé sous Linux jusqu'à ce qu'un mktemp
utilitaire (essentiellement compatible) soit ajouté à la coreutils de GNU en 2007. Juste pour dire, on ne peut pas vraiment dire qu'il mktemp
s'agit d'un utilitaire GNU.
Certains coques ont la fonctionnalité intégrée.
zsh
La =(...)
forme de substitution de processus utilise un fichier temporaire. Par exemple, =(echo test)
étend le chemin du fichier temporaire qui contient test\n
.
$ {cat $file; ls -l /dev/fd/3; echo test2 >&3; cat $file} 3<> ${file::==(echo test)}
test
lrwx------ 1 stephane stephane 64 Jan 30 11:19 /dev/fd/3 -> /tmp/zshMLbER0
test2
Ce fichier est automatiquement supprimé une fois la commande terminée.
Here-files ou here-strings in bash
et zsh
sont implémentés en tant que fichiers temporaires supprimés.
Donc si vous le faites:
exec 3<<< test
Le descripteur de fichier 3 est connecté à un fichier temporaire supprimé qui contient test\n
.
Vous pouvez obtenir son contenu avec:
cat <&3
Si vous êtes sous Linux, vous pouvez également lire ou écrire dans ce fichier via /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(Certains autres shells utilisent des pipes, ou peuvent utiliser /dev/null
si la doc est vide).
Il n'y a pas d' mktemp
utilitaire POSIX. Cependant, POSIX spécifie une mkstemp(template)
API C et l' m4
utilitaire standard expose cette API avec la mkstemp()
fonction m4 du même nom.
mkstemp()
vous donne un nom de fichier avec une partie aléatoire dont il était garanti qu'elle n'existerait pas au moment où la fonction a été appelée. Il crée le fichier avec les autorisations 0600 sans aucune course.
Donc, vous pourriez faire:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Notez toutefois que vous devez gérer le nettoyage à la sortie. Toutefois, si vous ne devez écrire et lire le fichier qu'un nombre fixe de fois, vous pouvez l'ouvrir et le supprimer juste après sa création, comme pour le fichier here-doc / here- approche de chaîne ci-dessus:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
# open once for writing, twice for reading:
exec 3> "$tempfile" 4< "$tempfile" 5< "$tempfile"
rm -f -- "$tmpfile"
cmd >&3 # store something in the temp file
exec 3>&- # fd no longer needed
# read the content twice:
cat <&4
cat <&5
Vous pouvez ouvrir le fichier pour lecture une fois et lseek()
revenir en arrière entre deux lectures. Cependant, aucun utilitaire POSIX ne peut effectuer ce rembobinage ( ), vous ne pouvez donc pas le faire de manière portable dans un script POSIX ( zsh
( sysseek
intégré) et ksh93
( <#((...))
opérateur)). faites le cependant).
<()
=(...)
.
Voici une réponse légèrement améliorée dans la lignée de Hauke Laging:
#!/bin/bash
tmpfile=$(mktemp) # Create a temporal file in the default temporal folder of the system
# Lets do some magic for the tmpfile to be removed when this script ends, even if it crashes
exec {FD_W}>"$tmpfile" # Create file descriptor for writing, using first number available
exec {FD_R}<"$tmpfile" # Create file descriptor for reading, using first number available
rm "$tmpfile" # Delete the file, but file descriptors keep available for this script
# Now it is possible to work with the temporal file
echo foo >&$FD_W
echo bar >&$FD_W # Note that file descriptor always concatenates, not overwrites
cat <&$FD_R
Mon flux de travail généralement avec des fichiers temporaires est dû à un script bash que je teste. Je veux que tout soit clair pour tee
que je puisse voir que tout fonctionne et enregistrer la sortie pour la prochaine itération de mon processus. J'ai créé un fichier appelétmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
afin que je puisse l'utiliser comme
$ some_command --with --lots --of --stuff | tee $(tmp)
La raison pour laquelle j’aime le format de date et d’heure précédant les valeurs aléatoires, c’est que cela me permet de trouver facilement le fichier tmp que je viens de créer, et je n’ai pas à penser à comment le nommer la prochaine fois (et à me concentrer uniquement sur mon script dang travailler).