bashで一時ファイルを作成する


150

bashスクリプトで一時ファイルを作成する客観的により良い方法はありますか?

tempfile-123のように、頭に浮かんだものには通常名前を付けます。スクリプトが終了すると削除されるからです。現在のフォルダーで可能なtempfile-123を上書きする以外に、これを行うことの不利な点はありますか?または、より注意深く一時ファイルを作成することには利点がありますか?


1
一時ファイルを使用しないでください。代わりに一時ディレクトリを使用してください。また、mktempは使用しないでください。なぜここを参照してください:codeproject.com/Articles/15956/...を
ceving

17
@cevingその記事は、少なくともシェルコマンドmktemp(mktempライブラリの呼び出しではなく)に適用した場合、単に間違っています。mktempは制限付きのumaskでファイル自体を作成するため、与えられた攻撃は、攻撃者が攻撃対象と同じアカウントで操作している場合にのみ機能します。この場合、ゲームはすでに失われています。シェルスクリプトの世界でのベストプラクティスについては、mywiki.wooledge.org / BashFAQ / 062
Charles Duffy

tempfile(1)それが搭載されているシステムでも使用できます。
追って通知があるまで一時停止。

回答:


179

mktemp(1)manページには、かなりよくそれを説明します:

従来、多くのシェルスクリプトは、pidをサフィックスとして持つプログラムの名前を受け取り、それを一時ファイル名として使用しています。この種の命名方式は予測可能であり、それによって作成される競合状態は攻撃者が勝つことは簡単です。まだ劣っていますが、より安全なアプローチは、同じ命名スキームを使用して一時ディレクトリを作成することです。これにより、一時ファイルが破壊されないことが保証されますが、それでも単純なサービス拒否攻撃が可能です。これらの理由から、代わりにmktempを使用することをお勧めします。

スクリプトで、mktempを次のように呼び出します

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

これにより、作業可能な一時ディレクトリが作成され、実際のファイルに読みやすく便利な名前を安全に付けることができます。

mktemp標準ではありませんが、多くのプラットフォームに存在します。"X"は一般にランダム性に変換され、おそらくよりランダムになります。ただし、一部のシステム(ビジーボックスアッシュなど)では、このランダム性を他のシステムよりも大幅に制限しています


ちなみに、一時ファイルを安全に作成することは、シェルスクリプトよりも重要です。そのため、Pythonにはtempfile、perlにはFile :: Temp、rubyにはTempfileなどがあります。


1
-tオプションが推奨されていません:gnu.org/software/coreutils/manual/html_node/...
ティボーヴァース

7
最も安全で、クロスプラットフォームで使用する方法mktempは、と組み合わせるbasenameことmktemp -dt "$(basename $0). XXXXXXXXXX"です。せずに使用した場合basename、このようなエラーが出るかもしれませんあなたmktempを:無効なテンプレートを、 `/tmp/MOB-SAN-JOB1-183-ScriptBuildTask-7300464891856663368.sh.XXXXXXXXXX」はディレクトリの区切りが含まれています
i4niac

7
タイプミスは無視してください(余分なスペース)。mktemp -dt "$(basename $0).XXXXXXXXXX"正しい方法です。
i4niac 2014年

3
@ i4niac:あなたは必要なものを引用する$0スペースがOS Xの土地でたくさんありますが、mktemp -dt "$(basename "$0").XXXXXX"
Orwellophile

11
また、スクリプトの実行の最後にTEMPDIRを削除するにはすてきなことがありますtrap "rm -rf $mydir" EXIT
KumZ

43

はい、mktempを使用します。

一時ファイルを格納するために設計されたフォルダー内に一時ファイルを作成し、一意の名前を保証します。そのファイルの名前を出力します。

> mktemp
/tmp/tmp.xx4mM3ePQY
>

19

あなたは見てみたいかもしれません mktemp

mktempユーティリティは、指定されたファイル名テンプレートを受け取り、その一部を上書きして一意のファイル名を作成します。テンプレートは、/ tmp / tfile.XXXXXXXXXXのように、いくつかの「X」が付加された任意のファイル名です。末尾の「X」は、現在のプロセス番号とランダムな文字の組み合わせで置き換えられます。

詳細:man mktemp


11

より慎重な方法で一時ファイルを作成することに利点はありますか

一時ファイルは通常、/tmp他のすべてのユーザーとプロセスが読み取りと書き込みのアクセス権を持つ(などの)一時ディレクトリに作成されます(他のスクリプトはそこに新しいファイルを作成できます)。したがって、スクリプトはファイルの作成に注意する必要があります。たとえば、適切なアクセス許可(所有者に対してのみ読み取り、参照:などhelp umask)を使用してファイル名を簡単に推測できないようにする必要があります(理想的にはランダム)。そうしないと、ファイル名が一意でない場合、同じスクリプトが複数回実行されたときに競合が発生する可能性があります(例:競合状態))または一部の攻撃者は、一部の機密情報をハイジャックする(例:権限が開きすぎてファイル名が推測しやすい)か、ファイルを独自のバージョンのコードで作成/置換します(何が行われているかに応じてコマンドまたはSQLクエリを置き換えるなど)保管されています)。


次の方法で一時ディレクトリを作成できます。

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

または一時ファイル:

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

ただし、予測可能であり、安全とは見なされていません。

に従ってman mktemp、次のように読むことができます。

従来、多くのシェルスクリプトは、pidをサフィックスとして持つプログラムの名前を受け取り、それを一時ファイル名として使用しています。この種の命名方式は予測可能であり、それによって作成される競合状態は攻撃者が勝つことは簡単です。

安全のため、mktempコマンドを使用して一意の一時ファイルまたは一時ディレクトリを作成することをお勧めします(-d)。


2
正確には何が尋ねられたのではありません。しかし、それは完璧な解決策になる可能性があります。
jpbochi 2016年

1
@jpbochi質問への回答を改善しました。それが役立つかどうか私に知らせてください。
kenorb 2017年

2
それは確かに答えを改善します。しかし、私の賛成票はすでにあなたのものです。これ以上投票できません。私が持っている1つの提案は、何を説明し${0##*/}$$展開するか、それに関するいくつかのドキュメントにリンクすることです。
jpbochi 2017年

0

mktemp 特にしばらくファイルを操作する場合は、おそらく最も用途が広いでしょう。

ファイルを別のコマンドへの入力として一時的にのみ必要な場合は、プロセス置換演算子を 使用することもでき<()ます。例:

$ diff <(echo hello world) <(echo foo bar)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.