Odpowiedzi:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Możesz upewnić się, że plik zostanie usunięty po wyjściu ze skryptu (włączając zabójstwa i awarie), otwierając deskryptor pliku i usuwając go. Plik pozostaje dostępny (dla skryptu; tak naprawdę nie dla innych procesów, ale /proc/$PID/fd/$FD
jest obejściem), dopóki deskryptor pliku jest otwarty. Po zamknięciu (co jądro robi automatycznie po zakończeniu procesu) system plików usuwa plik.
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc
- z wyjątkiem systemów, które go nie mają.
exec 3> "$tmpfile"
zrobić? Czy to nie jest użyteczne tylko wtedy, gdy plik tmp jest samodzielnym skryptem?
cat <&3
da Bad file descriptor
. Byłbym wdzięczny, jeśli to naprawisz lub usuniesz; dezinformacja niewiele pomaga.
Użyj, mktemp
aby utworzyć tymczasowy plik lub katalog:
temp_file=$(mktemp)
Lub w kierunku direcotry:
temp_dir=$(mktemp -d)
Na końcu skryptu musisz usunąć plik tymczasowy / katalog:
rm ${temp_file}
rm -R ${temp_dir}
mktemp tworzy plik w /tmp
katalogu lub w drectory podanym z --tmpdir
argumentem.
trap "rm -f $temp_file" 0 2 3 15
zaraz po utworzeniu pliku, aby po wyjściu lub zatrzymaniu skryptu ctrl-C
plik był nadal usuwany.
EXIT
jest to jedyny hak trap
?
kill -9 $somepid
. Ten szczególny sygnał zabójstwa to natychmiastowa śmierć i nic innego się nie dzieje.
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXIT
Wystarczą pułapki .
Jeśli korzystasz z systemu, który ma mktemp , powinieneś użyć go jako innych odpowiedzi.
Z zestawem narzędzi 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
jest to jedyny hak trap
?
tmpfile
nadal będzie usuwany przed zakończeniem skryptu, ale nie, gdy skrypt otrzyma inne sygnały.
That's not what happens
?
mktemp
pochodzi z HP / UX z inną składnią. Todd C. Miller stworzył inny dla OpenBSD w połowie lat 90. (skopiowany przez FreeBSD i NetBSD), a później udostępnił go również jako samodzielne narzędzie (www.mktemp.org). Jest to ten, który był zwykle używany w Linuksie, dopóki mktemp
w 2007 r. Nie dodano (głównie kompatybilnego) narzędzia do GNU coreutils. Nie można powiedzieć, że tak naprawdę nie można powiedzieć, że mktemp
to narzędzie GNU.
Niektóre muszle mają wbudowaną funkcję.
zsh
jest =(...)
podstawienia proces wykorzystuje plik tymczasowy. Na przykład =(echo test)
rozwija się do ścieżki pliku tymczasowego, który zawiera 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
Plik ten jest automatycznie usuwany po zakończeniu wykonywania polecenia.
Pliki-tutaj lub ciągi-tu są bash
i zsh
są implementowane jako usunięte pliki tymczasowe.
Więc jeśli to zrobisz:
exec 3<<< test
Deskryptor pliku 3 jest połączony z usuniętym plikiem tymczasowym, który zawiera test\n
.
Możesz uzyskać jego zawartość za pomocą:
cat <&3
W systemie Linux można również czytać lub zapisywać do tego pliku za pośrednictwem /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(niektóre inne powłoki używają potoków lub mogą użyć, /dev/null
jeśli tutaj dokument jest pusty).
Nie ma mktemp
narzędzia POSIX. POSIX określa jednak mkstemp(template)
interfejs API języka C , a m4
standardowe narzędzie udostępnia interfejs API z mkstemp()
funkcją m4 o tej samej nazwie.
mkstemp()
daje nazwę pliku z losową częścią, która nie istniała w momencie wywołania funkcji. Tworzy plik z uprawnieniami 0600 w sposób bez wyścigu.
Więc możesz zrobić:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Zauważ jednak, że musisz wyjść z czyszczenia po wyjściu, ale jeśli musisz tylko napisać i odczytać plik określoną liczbę razy, możesz go otworzyć i usunąć zaraz po utworzeniu, jak w przypadku tutaj-doc / here- powyższe podejście łańcuchowe:
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
Możesz otworzyć plik do odczytu raz i przewinąć do tyłu między dwoma odczytami, jednak nie ma narzędzia POSIX, które może zrobić to przewijanie ( lseek()
), więc nie możesz tego zrobić przenośnie w skrypcie POSIX ( zsh
( sysseek
wbudowany) i ksh93
( <#((...))
operator) może zrób to jednak).
<()
=(...)
.
Oto nieco ulepszona odpowiedź w linii 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
Mój przepływ pracy zwykle z plikami tymczasowymi wynika z testowanego skryptu bash. Chcę tee
to poprawić, aby zobaczyć, że działa, i zapisać dane wyjściowe do następnej iteracji mojego procesu. Utworzyłem plik o nazwietmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
żebym mógł go używać jak
$ some_command --with --lots --of --stuff | tee $(tmp)
Powodem, dla którego podoba mi się data i godzina sformatowana przed losowymi wartościami, jest to, że pozwala mi łatwo znaleźć plik tmp, który właśnie utworzyłem, i nie muszę myśleć o tym, jak nazwać go następnym razem (i skupić się na otrzymaniu skryptu Dang pracować).