Відповіді:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Ви можете переконатися, що при видаленні скриптів файл видаляється (включаючи вбивства та збої), відкривши дескриптор файлу та видаливши його. Файл залишається доступним (для сценарію; насправді не для інших процесів, але /proc/$PID/fd/$FDє обхідним), поки дескриптор файлу відкритий. Коли воно закривається (що ядро робить автоматично, коли процес закінчується), файлова система видаляє файл.
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc- за винятком систем, у яких його немає.
exec 3> "$tmpfile"? Хіба це не тільки корисно, якщо tmpfile є автономним сценарієм?
cat <&3дадуть Bad file descriptor. Буду вдячний, якщо ви його виправите чи вилучите; дезінформація не дуже допомагає.
Використовуйте mktempдля створення тимчасового файлу чи каталогу:
temp_file=$(mktemp)
Або для режисери:
temp_dir=$(mktemp -d)
Наприкінці сценарію вам потрібно видалити тимчасовий файл / dir:
rm ${temp_file}
rm -R ${temp_dir}
mktemp створює файл у /tmpкаталозі або в деривації, заданому --tmpdirаргументом.
trap "rm -f $temp_file" 0 2 3 15відразу після створення файлу, щоб, коли скрипт вийшов або зупинився, ctrl-Cфайл все-таки видалився.
EXITце єдиний гачок trap?
kill -9 $somepid. Цей конкретний сигнал вбивства - це смерть, і нічого іншого не відбувається.
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXITдосить.
Якщо ви працюєте в системі, яка має mktemp , вам слід використовувати її як інші відповіді.
З інструментальним інструментом 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це єдиний гачок trap?
tmpfileвсе-таки видаляйте перед виходом сценарію, але не тоді, коли сценарій отримав інші сигнали.
That's not what happens?
mktempвиник у HP / UX з іншим синтаксисом. У середині 90-х Тод К. Міллер створив інший для OpenBSD (скопійований FreeBSD та NetBSD), а згодом також став доступним як окрема утиліта (www.mktemp.org). Це той, який зазвичай використовувався в Linux, поки mktempв 2007 році до ядра GNU не була додана (в основному сумісна) утиліта. Просто сказати, що реально не можна сказати mktemp, це утиліта GNU.
Деякі снаряди мають вбудовану функцію.
zsh«S =(...)форма заміщення процесу використовує тимчасовий файл. Наприклад, =(echo test)розширюється до шляху тимчасового файлу, який містить 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
Цей файл автоматично видаляється після завершення команди.
Тут-файли або тут-рядки в bashі zshреалізуються як видалені тимчасові файли.
Отже, якщо ви робите:
exec 3<<< test
Дескриптор файлу 3 підключений до видаленого тимчасового файлу, який містить test\n.
Ви можете отримати його вміст за допомогою:
cat <&3
Якщо в Linux, ви також можете читати або записувати в цей файл через /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(деякі інші оболонки використовують труби, або можуть використовувати їх, /dev/nullякщо тут документ пустий).
Немає mktempутиліти POSIX. POSIX, однак, визначає mkstemp(template)API C , і m4стандартна утиліта розкриває цей API з mkstemp()функцією m4 з тим же ім'ям.
mkstemp()дає вам ім'я файлу з випадковою частиною, яка гарантувалась, що не існує на момент виклику функції. Він створює файл з дозволами 0600 без гонки.
Отже, ви можете зробити:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Однак зауважте, що вам потрібно обробити очищення після виходу, хоча якщо вам потрібно лише записати та прочитати файл фіксовану кількість разів, ви можете відкрити його та видалити відразу після створення, як для here-doc / here- рядковий підхід вище:
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
Ви можете відкрити файл для читання один раз і перемотати назад між двома читаннями, однак не існує утиліти POSIX, яка могла б зробити це перемотування ( lseek()), тому ви не можете робити це портативно в сценарії POSIX ( zsh( sysseekвбудований) та ksh93( <#((...))оператор) зробіть це, хоча).
<()
=(...).
Ось трохи покращена відповідь у рядку Хауке Лагінга:
#!/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
Мій робочий процес, як правило, з тимчасовими файлами, пов'язаний з певним сценарієм bash, який я тестую. Я хочу teeце зробити, щоб я міг бачити, що він працює, і зберегти висновок для наступної ітерації мого процесу. Я створив файл під назвоюtmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
щоб я міг нею користуватися
$ some_command --with --lots --of --stuff | tee $(tmp)
Причина, що мені подобається відформатовану дату перед випадковими значеннями, - це дозволяє мені знайти файл tmp, який я щойно створив, і мені не потрібно думати про те, як назвати його наступного разу (і зосередитися на тому, щоб просто отримати мій сценарій dang працювати).