Tạo tập tin tạm thời trong bash


150

Có cách nào khách quan hơn để tạo các tệp tạm thời trong tập lệnh bash không?

Tôi thường chỉ đặt tên cho chúng bất cứ điều gì xuất hiện trong đầu tôi, chẳng hạn như tempfile-123, vì nó sẽ bị xóa khi tập lệnh kết thúc. Có bất kỳ bất lợi nào khi làm điều này ngoài việc ghi đè tempfile-123 có thể có trong thư mục hiện tại không? Hoặc có bất kỳ lợi thế trong việc tạo một tập tin tạm thời một cách cẩn thận hơn?


1
Đừng sử dụng các tập tin tạm thời. Sử dụng các thư mục tạm thời thay thế. Và đừng sử dụng mktemp. Xem tại đây tại sao: codeproject.com/Articles/15956/ Cách
ceving

17
@ceving Bài viết đó đơn giản là sai, ít nhất là khi áp dụng cho lệnh shell mktemp (trái ngược với lệnh gọi thư viện mktemp). Vì mktemp tự tạo tệp với một ô hạn chế, cuộc tấn công được đưa ra chỉ hoạt động nếu kẻ tấn công đang hoạt động trong cùng một tài khoản với attackee ... trong trường hợp trò chơi đã bị mất. Để biết cách thực hành tốt nhất trong thế giới kịch bản shell, hãy xem mywiki.wooledge.org/BashFAQ/062
Charles Duffy

Bạn cũng có thể sử dụng tempfile(1)trên các hệ thống có nó.
Tạm dừng cho đến khi có thông báo mới.

Câu trả lời:


179

Các mktemp(1)trang người đàn ông giải thích nó khá tốt:

Theo truyền thống, nhiều tập lệnh shell lấy tên của chương trình với pid làm hậu tố và sử dụng nó làm tên tệp tạm thời. Kiểu sơ đồ đặt tên này có thể dự đoán được và điều kiện cuộc đua mà nó tạo ra dễ dàng cho kẻ tấn công giành chiến thắng. Một cách tiếp cận an toàn hơn, mặc dù vẫn kém hơn, là tạo một thư mục tạm thời bằng cách sử dụng cùng một sơ đồ đặt tên. Mặc dù điều này không cho phép một người đảm bảo rằng một tệp tạm thời sẽ không bị lật đổ, nhưng nó vẫn cho phép một cuộc tấn công từ chối dịch vụ đơn giản. Vì những lý do này, nên sử dụng mktemp thay thế.

Trong một kịch bản, tôi gọi mktemp một cái gì đó như

mydir=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")

trong đó tạo ra một thư mục tạm thời tôi có thể làm việc và trong đó tôi có thể đặt tên một cách an toàn cho các tệp thực tế một cái gì đó có thể đọc và hữu ích.

mktempkhông phải là tiêu chuẩn, nhưng nó tồn tại trên nhiều nền tảng. Các chữ "X" nói chung sẽ được chuyển đổi thành một số ngẫu nhiên và nhiều hơn có thể sẽ ngẫu nhiên hơn; tuy nhiên, một số hệ thống (busybox ash, cho một) hạn chế sự ngẫu nhiên này đáng kể hơn các hệ thống khác


Nhân tiện, việc tạo các tệp tạm thời an toàn rất quan trọng đối với nhiều thứ chứ không chỉ là kịch bản shell. Đó là lý do python có tempfile , perl có File :: Temp , ruby ​​có Tempfile , v.v.


1
Tùy chọn -t không được dùng nữa: gnu.org/software/coreutils/manual/html_node/ Kẻ
Tibor Vass

7
Có vẻ như cách an toàn nhất và đa nền tảng nhất để sử dụng mktemplà kết hợp với basename, như vậy mktemp -dt "$(basename $0). XXXXXXXXXX". Nếu được sử dụng mà không có basenamebạn có thể gặp lỗi như mktemp: mẫu không hợp lệ này, `/tmp/MOB-SAN-JOB1-183-ScriptBuildTask-7300463611856663368.sh.XXXXXXXXX ', có chứa dấu tách thư mục .
i4niac

7
Bỏ qua họ đánh máy (không gian thêm). mktemp -dt "$(basename $0).XXXXXXXXXX"là cách chính xác.
i4niac

3
@ i4niac: bạn cần trích dẫn rằng $0, có rất nhiều không gian trên mảnh đất của OS X.mktemp -dt "$(basename "$0").XXXXXX"
Orwellophile

11
Ngoài ra, có thể tốt hơn để xóa tempdir khi kết thúc quá trình thực thi tập lệnh:trap "rm -rf $mydir" EXIT
KumZ

43

Có, sử dụng mktemp .

Nó sẽ tạo một tệp tạm thời bên trong một thư mục được thiết kế để lưu trữ các tệp tạm thời và nó sẽ đảm bảo cho bạn một tên duy nhất. Nó xuất ra tên của tệp đó:

> mktemp
/tmp/tmp.xx4mM3ePQY
>

19

Bạn có thể muốn nhìn vào mktemp

Tiện ích mktemp lấy mẫu tên tệp đã cho và ghi đè lên một phần của nó để tạo một tên tệp duy nhất. Mẫu có thể là bất kỳ tên tệp nào có số 'Xs' được thêm vào nó, ví dụ /tmp/tfile.XXXXXXXXXX. Các dấu 'X' được thay thế bằng sự kết hợp của số quy trình hiện tại và các chữ cái ngẫu nhiên.

Để biết thêm chi tiết: người đàn ông mktemp


11

Có bất kỳ lợi thế nào trong việc tạo một tập tin tạm thời một cách cẩn thận hơn

Các tệp tạm thời thường được tạo trong thư mục tạm thời (chẳng hạn như /tmp) nơi tất cả người dùng và quy trình khác có quyền truy cập đọc và ghi (bất kỳ tập lệnh nào khác có thể tạo các tệp mới ở đó). Do đó, tập lệnh nên cẩn thận về việc tạo các tệp như sử dụng với quyền phù hợp (ví dụ: chỉ đọc cho chủ sở hữu, xem help umask:) và tên tệp không nên dễ đoán (lý tưởng ngẫu nhiên). Mặt khác, nếu tên tệp không phải là duy nhất, nó có thể tạo xung đột với cùng một tập lệnh được chạy nhiều lần (ví dụ: điều kiện cuộc đua) hoặc một số kẻ tấn công có thể chiếm quyền điều khiển một số thông tin nhạy cảm (ví dụ: khi quyền quá mở và tên tệp dễ đoán) hoặc tạo / thay thế tệp bằng phiên bản mã của riêng chúng (như thay thế các lệnh hoặc truy vấn SQL tùy thuộc vào nội dung lưu trữ).


Bạn có thể sử dụng cách tiếp cận sau để tạo thư mục tạm thời:

TMPDIR=".${0##*/}-$$" && mkdir -v "$TMPDIR"

hoặc tập tin tạm thời:

TMPFILE=".${0##*/}-$$" && touch "$TMPFILE"

Tuy nhiên nó vẫn có thể dự đoán và không được coi là an toàn.

Theo man mktemp, chúng ta có thể đọc:

Theo truyền thống, nhiều tập lệnh shell lấy tên của chương trình với pid làm hậu tố và sử dụng nó làm tên tệp tạm thời. Kiểu sơ đồ đặt tên này có thể dự đoán được và điều kiện cuộc đua mà nó tạo ra dễ dàng cho kẻ tấn công giành chiến thắng.

Vì vậy, để an toàn, nên sử dụng mktemplệnh để tạo tệp hoặc thư mục tạm thời duy nhất ( -d).


2
không chính xác những gì đã được hỏi. Tuy nhiên, nó có thể là một giải pháp hoàn hảo.
jpbochi

1
@jpbochi Tôi đã cải thiện câu trả lời để giải quyết câu hỏi. Hãy cho tôi biết nếu nó giúp được bạn.
kenorb

2
Nó thực sự cải thiện câu trả lời. Upvote của tôi đã là của bạn, mặc dù. Không thể bình chọn nhiều hơn. Một đề nghị tôi có là giải thích những gì ${0##*/}$$mở rộng, hoặc liên kết đến một số tài liệu về nó.
jpbochi

0

mktemp có lẽ là linh hoạt nhất, đặc biệt nếu bạn có kế hoạch làm việc với tệp trong một thời gian.

Bạn cũng có thể sử dụng toán tử thay thế quy trình <() nếu bạn chỉ cần tệp tạm thời làm đầu vào cho lệnh khác, ví dụ:

$ diff <(echo hello world) <(echo foo bar)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.