Shell Script mktemp、一時的な名前付きパイプを作成する最良の方法は何ですか?


30

で一時ファイルを作成するのが最善であると認識していますがmktemp、名前付きパイプはどうですか?

私は物事を可能な限りPOSIX準拠にすることを好みますが、Linuxのみが許容されます。私が書いているように、バシズムを避けることは私の唯一の厳しい基準dashです。

回答:


41
tmppipe=$(mktemp -u)
mkfifo -m 600 "$tmppipe"

既存のファイルまたはシンボリックリンクによってハイジャックされる傾向がある通常のファイル作成とは異なり、名前パイプスルーmkfifoまたは基礎となる関数の作成は、指定された場所に新しいファイルを作成するか、失敗します。: >foo攻撃者がその出力を予測できる場合、攻撃者はmktemp自分用にターゲットファイルを作成できるため、そのようなものは安全ではありません。しかしmkfifo foo、そのようなシナリオでは失敗します。

POSIXの完全な移植性が必要な場合、mkfifo -m 600 /tmp/myfifoハイジャックに対して安全ですが、サービス拒否の危険があります。強力なランダムファイル名ジェネレータにアクセスできない場合、再試行を管理する必要があります。

一時ファイルに関する微妙なセキュリティ問題を気にしない場合は、単純なルールに従うことができます。プライベートディレクトリを作成し、そこにすべてを保持します。

tmpdir=
cleanup () {
  if [ -n "$tmpdir" ] ; then rm -rf "$tmpdir"; fi
  if [ -n "$1" ]; then kill -$1 $$; fi
}
tmpdir=$(mktemp -d)
trap 'cleanup' EXIT
trap 'cleanup HUP' HUP
trap 'cleanup TERM' TERM
trap 'cleanup INT' INT
mkfifo "$tmpdir/pipe"

私は実際、昨日早くにこれを自分のソリューションとして選択しました。誰かがそれを投稿するのか、それとももっと良いものを公開するのかを待っていました。私の場合、dirが進むべき道でもあると感じました。関係なく...助けてくれてありがとう。
JMベッカー

1
trapコマンドはすべきではありませんtrap "rm -rf '$tempdir'" EXIT HUP INT TERMか?独自の変数展開を行うことができますか?
シックス・

@Six トラップがトリガーされたときではなく$tempdirtrapコマンドが評価されたときにコマンドが展開されます。この場合、値にtempdir単一引用符が含まれているとコードがひどく壊れるのを除いて、違いはありませんが、私のコードは常に機能します。
ジル 'SO-悪であるのをやめる'

@Gillesそれは素晴らしい機能です。幸運なしに一重引用符の例を試したので、トラップは実行時に変数を評価できないと思いました。私$tempdirはローカルに宣言され、トラップがアクセスできるようにグローバルに定義する必要があることが判明しました。作るには...今感じる
シックス・

1
@Gilles ... $tempdir が変わらない限り、これは基本的にすべての目的に受け入れられます。同じ名前を使用して複数の一時ファイル/
ディレクトリ

3

より安全な代替方法はmktemp、ディレクトリを安全に作成するために使用し、名前付きパイプをそのディレクトリ内に配置し、最後にそれを削除rm -R $dirすることです。


FIFO mktempが実際に受け入れられる唯一の回答であったため、ディレクトリにFIFOを作成することを選択しました。
JMベッカー

2

「ドライラン」オプションを使用します。

mkfifo $(mktemp -ut pipe.XXX)

1
マニュアルページによると、-uオプションの使用は「推奨されていません」。
-dogbane

@dogbaneの使用もそうですが、-t確実に機能する限り、私はそれを使います。
ポレモン

申し訳ありませんが、それ-tは落胆しています。
-dogbane

2
@dogbane何らかの形で重要な場合は、mkstemp()関数(linux.die.net/man/3/mkstemp)を呼び出す小さなCアプリケーションを作成します。-tスイッチは、それが、落胆されていない-p、私の悪いです。
ポレモン

1

を使用mktempして一時ファイルを作成し、それを削除して、同じ名前の名前付きパイプを作成できます。

例えば:

TMPPIPE=$(mktemp -t pipe.XXX) && {
    rm -f $TMPPIPE
    mkfifo $TMPPIPE
}

$TMPPIPE前に削除すると、mkfifo「安全でない」問題が回避されTMPPIPE=`mktemp -u` ; mkfifo $TMPPIPEますか?
JMベッカー

1
@TechZilla mkfifoは、シェルからの通常の通常のファイル作成とは異なり、実際には安全です。そうでない場合、ファイルを作成してから削除してもまったく役に立ちません(実際、攻撃者がファイル名を推測することを要求しないため、攻撃者の仕事が大幅に促進されます)。したがって、dogbaneの答えは機能しますが、中間ファイルの作成は役に立たない複雑です。
ジル 'SO-悪であるのをやめる

1
@Gilles、オプション「安全でない」mktempと呼ばれるマニュアルページをどのように知ってい-uますか?
JMベッカー

@dogbane、私はあなたの答えに賛成票を投じました。ただし、私はすでに昨日これを完了しました。だから、私がmktemp -dあなたを使ったとしても、あなたのインプットにはまだいくつかのポイントがあります。すべてのあなたの助けをありがとう、本当に感謝します!
JMベッカー

1
@TechZilla mktemp -uは、サービス拒否に対する保護を提供するため(生成する名前が十分に予測できない場合)、通常のファイルを作成する場合は安全ではありませんが、攻撃者がプログラムの鼻の下でファイルを作成することを防ぎません。通常のファイルの代わりにfifoを作成することは、manページが対処しないまれなユースケースです。
ジル「SO-悪であるのをやめる」

0

使用mkfifoまたはmknod名前によってパイプにアクセスできる2つの独立したプロセスによってUnixの、中-ライターなどの他の一つのプロセスがリーダとして開くことができ、そして。

mkfifo my_pipe
gzip -9 -c < my_pipe > out.gz
cat file > my_pipe

名前付きパイプは、他のファイルと同様に削除できます。

rm my_pipe

mkfifo --mode=0666 /tmp/namedPipe
gzip --stdout -d file.gz > /tmp/namedPipe

NamedPipeは、一度だけ読み取るための通常のファイルとして使用できます。

http://www.linuxjournal.com/article/2156


2
私は名前付きパイプについて完全に知っていmkfifoます。これは、一時ディレクトリの作成に関する問題よりも、一時的な名前付きパイプに関する私の質問には対応していませんmkdir
JMベッカー

2
これは、名前付きパイプmktemp安全に作成するため対処する問題にどのように対処しますか?
カム

1
わかりました。最善の方法は/ tmpの下に作成することです。これらは定義上一時ファイルであり、システムが再起動するとクリアされます。または、さらに良いことに、mktemp結果自体からnamedpipeを作成するシェル関数を使用します(もちろん、まず一時ファイルを削除してmkfifoから、同じファイルで実行します)。 mktemp一時ディレクトリを作成するために使用することもできます-t -d。スイッチで試してください。
ニキルマーリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.