非解釈コンテキストで実行されたときに特定のシェルの PID を調べると、奇妙な動作が観察されます。
以下の例では、予想どおり PID がシェルを指していることがわかります。
sh-4.3$ echo 'readlink /proc/$$/exe' | /bin/bash
/bin/bash
sh-4.3$ echo 'readlink /proc/$$/exe' | /bin/tcsh
/bin/tcsh
sh-4.3$ echo 'readlink /proc/$$/exe' | /bin/zsh
/usr/bin/zsh
-c
ただし、パイプの代わりに を使用して同じアイデアを試すと、Bourne 互換シェルの PID はreadlink
シェルの代わりにになります。
sh-4.3$ /bin/tcsh -c 'readlink /proc/$$/exe'
/bin/tcsh
sh-4.3$ /bin/bash -c 'readlink /proc/$$/exe'
/usr/bin/readlink
sh-4.3$ /bin/zsh -c 'readlink /proc/$$/exe'
/usr/bin/readlink
また、コマンドを単一のステートメントではなく複合ステートメントにすると、ほとんどの場合、期待どおりの結果が得られることが分かりました (zsh
少し頑固なようです)。
sh-4.3$ /bin/bash -cf 'readlink /proc/$$/exe | cat'
/bin/bash
sh-4.3$ /bin/zsh -cf 'readlink /proc/$$/exe | cat'
/usr/bin/zsh
sh-4.3$ /bin/bash -cf 'readlink /proc/$$/exe; :'
/bin/bash
sh-4.3$ /bin/zsh -cf 'readlink /proc/$$/exe; :'
/bin/zsh
sh-4.3$ /bin/bash -cf ':; readlink /proc/$$/exe'
/bin/bash
sh-4.3$ /bin/zsh -cf ':; readlink /proc/$$/exe'
/usr/bin/readlink
sh-4.3$ /bin/bash -c 'readlink /proc/$$/exe > /dev/stdout'
/bin/bash
sh-4.3$ /bin/zsh -c 'readlink /proc/$$/exe > /dev/stdout'
/usr/bin/readlink
おそらく、Bourne互換シェルは、呼び出しが単一のステートメントとして実行できるかどうかをチェックし、実行できる場合はexecv
実際にシェルを呼び出す代わりに、またはそれに類するものを使用します。
私の質問:
- 私の疑いは正しいでしょうか? もしそうなら、その動機は何だったのでしょうか?
- この動作を無効にすることはできますか?