私はbashファイルのリダイレクトをかなりうまく処理していると思います。一般的に「猫の無駄な使用「しかし、スクリプトで予期しない動作が発生しましたが、なぜこれが起こるのかを知りたいです。
bashスクリプトで次のように実行します。
somecommand < file1 > file2
私の期待は、file1が安全で読み取り専用で開くことです。実際にfile1を上書きできることがわかりました。どのように/なぜこれが起こり、それに頼らずに解決することができますかcat
?
私が想像するように動作している場合(プロセスは直接rwファイル記述子で終わるのですか?)このようにファイルをリダイレクトすることは危険であると見なされるべきだと思われますが、以前はこれを見たことがありません。
私の場合にいくつかの詳細を追加するには、問題のコマンドは次のとおりです。標準操作手順、バックグラウンドでいくつかのGPG操作を実行します。 GPGパスワードプロンプトは、入力に使用されたファイルに上書きされることがあります。私が使用する完全なコマンドは次のとおりです。
sops --input-type json --output-type json -d /dev/stdin < ./secrets/file.json > ./secrets/file-decrypted.json
私はそれ以降に切り替えて、cat file1 | sops.. > file2
すべてが期待どおりに機能しました。私はこれが「猫に役に立たない使用」と言ったでしょう。しかし、それはもはやそれほど役に立たないようです!
†最初のメッセージが表示されたら、gpg-agentが実行されていないようです。
ベストアンサー1
これは、Linux(およびCygwinですが、通常他のシステムではない)で/dev/stdin
(実質的に)実装されている方法によるものです。/proc/self/fd/0
Linuxで開く/dev/stdin
ことは、実行するのとは異なりますdup(0)
。 fd 0で開いたファイルと同じファイルを再度開くだけです。共有されませんファイル説明を開くfd 0参照(読み取り専用モードを使用)、完全に無関係な新しい値を取得するファイル説明を開く、モードはで指定されたものと同じですopen()
。
したがって、読み取り+書き込みモードでsops -d /dev/stdin
開き、fd 0が/dev/stdin
読み取り専用で開くと、読み取り+書き込みモードで開きます。/some/file
/some/file
実際にcmd /dev/stdin < file
はcmd file < file
。これは/dev/stdin
シンボリックリンクにすぎないことがわかりますfile
。
/tmp$ namei -l /dev/stdin < file
f: /dev/stdin
drwxr-xr-x root root /
drwxr-xr-x root root dev
lrwxrwxrwx root root stdin -> /proc/self/fd/0
drwxr-xr-x root root /
dr-xr-xr-x root root proc
lrwxrwxrwx root root self -> 73569
dr-xr-xr-x stephane stephane 73569
dr-x------ stephane stephane fd
lr-x------ stephane stephane 0 -> /tmp/file
drwxr-xr-x root root /
drwxrwxrwt root root tmp
-rw-r--r-- stephane stephane file
状況がさらに悪化する可能性があります。 O_TRUNC で開くとファイルが切り捨てられます。 fd 0がパイプの読み取り端を指して書き込み/dev/stdin
専用モードで開くと、パイプのもう一方の端が得られます。
ただし、以下を使用してください。
cat file | cmd /dev/stdin
パイプがすべての人に表示されるため、適用cmd
を防ぎます。書き込み専用モードで開いても再び戻ることはできず、パイプの書き込み端にのみ到達し、読み取り終了の唯一のファイル記述子はstdinです。file
cmd
file
cmd
他のオペレーティングシステムではこの問題は発生しません。/dev/stdin
これを開くのはaを実行するのと同じであるためdup(0)
、同じ結果が得られるからです。ファイル説明を開く互換性のないモードで開くと、open()
システムコールが失敗します。
1技術的に@ user414777がコメントで指摘したように/proc/<pid>/fd/<fd>
、魔法のシンボリックリンクたとえば、通常のシンボリックリンクが行けない場所に移動できますが、それを開くと、パスチェックステップの後に通常のシンボリックリンクのように動作し、ターゲットファイルを開くだけです。