Câu trả lời:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Bạn có thể đảm bảo rằng một tệp bị xóa khi các tập lệnh thoát (bao gồm cả giết chết và sự cố) bằng cách mở một mô tả tệp vào tệp và xóa nó. Tệp luôn có sẵn (đối với tập lệnh; không thực sự cho các quy trình khác nhưng /proc/$PID/fd/$FD
là một công việc xung quanh) miễn là bộ mô tả tệp được mở. Khi nó được đóng (mà kernel tự động thực hiện khi quá trình thoát), hệ thống tập tin sẽ xóa tập tin.
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc
- ngoại trừ các hệ thống không có nó.
exec 3> "$tmpfile"
làm gì? Điều đó không hữu ích nếu tmpfile là một tập lệnh độc lập?
cat <&3
sẽ cho Bad file descriptor
. Tôi sẽ đánh giá cao nếu bạn sửa nó hoặc gỡ bỏ nó; thông tin sai lệch không giúp được gì nhiều.
Sử dụng mktemp
để tạo một tập tin hoặc thư mục tạm thời:
temp_file=$(mktemp)
Hoặc cho một direcotry:
temp_dir=$(mktemp -d)
Khi kết thúc tập lệnh, bạn phải xóa tập tin / thư mục tạm thời:
rm ${temp_file}
rm -R ${temp_dir}
mktemp tạo tập tin trong /tmp
thư mục hoặc trong phần bổ sung được cung cấp với --tmpdir
đối số.
trap "rm -f $temp_file" 0 2 3 15
ngay sau khi tạo tệp để khi tập lệnh thoát hoặc bị dừng với ctrl-C
tệp vẫn bị xóa.
EXIT
là cái móc duy nhất trap
?
kill -9 $somepid
. Tín hiệu tiêu diệt đặc biệt đó là insta-death không có gì khác xảy ra.
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXIT
là đủ.
Nếu bạn đang sử dụng hệ thống có mktemp , bạn nên sử dụng nó làm câu trả lời khác.
Với công cụ 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
là cái móc duy nhất cho trap
?
tmpfile
vẫn bị xóa trước khi thoát tập lệnh, nhưng không phải khi tập lệnh nhận được tín hiệu khác.
That's not what happens
gì?
mktemp
có nguồn gốc từ HP / UX với một cú pháp khác nhau. Todd C. Miller đã tạo một cái khác cho OpenBSD vào giữa những năm 90 (được sao chép bởi FreeBSD và NetBSD) và sau đó làm cho nó cũng có sẵn như là một tiện ích độc lập (www.mktemp.org). Đó là mktemp
tiện ích thường được sử dụng trên Linux cho đến khi tiện ích (hầu hết tương thích) được thêm vào lõi GNU trong năm 2007. Chỉ cần nói rằng người ta không thể thực sự nói mktemp
là tiện ích GNU.
Một số vỏ có tính năng tích hợp.
zsh
's =(...)
hình thức thay thế tiến trình sử dụng một tập tin tạm thời. Ví dụ, =(echo test)
mở rộng tới đường dẫn của tệp tạm thời chứa 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
Tập tin đó được tự động loại bỏ, khi lệnh đã kết thúc.
Các tệp ở đây hoặc các chuỗi ở đây bash
và zsh
được triển khai dưới dạng các tệp tạm thời bị xóa.
Vì vậy, nếu bạn làm:
exec 3<<< test
Bộ mô tả tệp 3 được kết nối với một tệp tạm thời bị xóa có chứa test\n
.
Bạn có thể lấy nội dung của nó với:
cat <&3
Nếu trên Linux, bạn cũng có thể đọc hoặc ghi vào tệp đó thông qua /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(một số vỏ khác sử dụng đường ống hoặc có thể sử dụng /dev/null
nếu tài liệu ở đây trống).
Không có mktemp
tiện ích POSIX. Tuy nhiên, POSIX chỉ định mkstemp(template)
API C và m4
tiện ích tiêu chuẩn hiển thị API đó với mkstemp()
chức năng m4 cùng tên.
mkstemp()
cung cấp cho bạn một tên tệp với một phần ngẫu nhiên được đảm bảo không tồn tại tại thời điểm hàm được gọi. Nó tạo tập tin với quyền 0600 theo cách không có chủng tộc.
Vì vậy, bạn có thể làm:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Tuy nhiên, xin lưu ý rằng bạn cần xử lý dọn dẹp khi thoát, mặc dù nếu bạn chỉ cần viết và đọc tệp một số lần cố định, bạn có thể mở nó và xóa nó ngay sau khi tạo như thế cho tài liệu này ở đây-doc / here- cách tiếp cận chuỗi trên:
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
Bạn có thể mở tệp để đọc một lần và tua lại giữa hai lần đọc, tuy nhiên không có tiện ích POSIX nào có thể thực hiện việc tua lại đó ( lseek()
), vì vậy bạn không thể thực hiện được điều đó trong tập lệnh POSIX ( zsh
( sysseek
dựng sẵn) và ksh93
( <#((...))
toán tử) làm điều đó mặc dù).
<()
=(...)
.
Dưới đây là một câu trả lời được cải thiện một chút trong dòng của Hauke Laging's:
#!/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
Quy trình làm việc của tôi thường với các tệp tạm thời là do một số tập lệnh bash tôi đang thử nghiệm. Tôi muốn tee
nó lên để tôi có thể thấy rằng nó hoạt động và lưu kết quả đầu ra cho lần lặp tiếp theo của quy trình của tôi. Tôi đã tạo một tệp có têntmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
để tôi có thể sử dụng nó như
$ some_command --with --lots --of --stuff | tee $(tmp)
Lý do tôi thích datetime được định dạng trước các giá trị ngẫu nhiên là vì nó cho phép tôi tìm tệp tmp mà tôi vừa thực hiện dễ dàng và tôi không phải suy nghĩ về việc đặt tên cho lần sau (và tập trung vào việc lấy tập lệnh dang của tôi làm việc).