cronから呼び出すときにインタプリタが/ bin / bashであることを証明する方法は?

cronから呼び出すときにインタプリタが/ bin / bashであることを証明する方法は?

これは私にとって少し混乱しています。

次のcronjobを単独で試すとき:

* * * * * /bin/bash -c "readlink /proc/$$/exe >> /root/printenv"
* * * * * /bin/bash -c "readlink /proc/$PPID/exe >> /root/printenv"
* * * * * /bin/bash -c "readlink /proc/self/exe >> /root/printenv"
* * * * * /bin/bash -c "ps -h -o comm -p $$ >> /root/printenv"
* * * * * /bin/bash -c "echo $SHELL" >> /root/printenv

私はそれぞれ次のような結果を得ます。

/bin/dash
/usr/sbin/cron
/bin/readlink
sh
/bin/sh

このようにcronで呼び出すと、/bin/bashどんな状況でも報告できないようです。

直接cronjobで""が解釈されている* * * * * /bin/bash -c "command"ことをどのように証明できますか?command/bin/bash

後で参考にする回答:

二重引用符を一重引用符に変更すると、正しいシェルが返されます。

* * * * * /bin/bash -c 'readlink /proc/$$/exe >> /root/printenv'

に戻る:

/bin/bash

以下の回答に貢献してくださった皆様に感謝します。

答え1

この場合、私のデフォルトのシェルはbashあり、テストを実行しました。

sh -c 'echo $0'

結果:sh

sh -c "echo $0"

結果:-bash

 bash -c 'echo $0'

結果:bash

 bash -c "echo $0"

結果:-bash

'一重引用符の後に-cスイッチを使用する必要があるようです。

答え2

すべてのコマンドの問題は、誤った引用符を使用していることです。 crontabの各コマンドは、シェルで処理されるシェルコードの断片です。 crontab コマンド処理シェルはSHELLcrontab ファイルの変数設定で定義され、デフォルトは/bin/sh.

/bin/sh(または互換性のあるシェル)がスクリプトを実行したときに/bin/bash -c "readlink /proc/$$/exe >> /root/printenv"コマンドラインを解析した後のステップの1つは、変数またはコマンドの置き換えを実行することです。これには変数置換があります。つまり、$$二重引用符で囲まれた文字列の内側です。 soを$$プロセスのプロセスIDに置き換えます/bin/sh。プロセスIDが1234であると仮定します。 cronによって呼び出されたシェルは/bin/bash引数-creadlink /proc/1234/exe >> /root/printenv。出力は、これがへの/bin/shシンボリックリンクであることを示します/bin/bash

二重引用符の代わりに一重引用符を使用すると、cronによって呼び出されたシェルは変数置換を実行せず、代わりに引数を使用してコマンドを実行/bin/bash-cますreadlink /proc/$$/exe >> /root/printenv。その後、Bashはコマンドを解析し、$$それを独自のプロセスIDに置き換えてから、readlink引数を使用して実行します1234

シェルによっては、このコマンドの出力はシェルバイナリであってもなくてもよい/bin/readlink。その理由は、bash(および他の多くのシェル)に最適化があるためです。外部コマンドを使用すると、子プロセスでコマンドを実行せずに、代わりにシェルのプロセスイメージを置き換えます。 (Unixでのプログラムの実行は、常に次のように行われます。プロセスイメージを別のイメージに置き換える;プログラム通常 自分をコピー直前ですが、義務事項ではありません。 )bashは、実行がreadlink最後に実行する必要があるタスクであることを検出するため、readlink同じプロセスで1234を実行するため、readlink /proc/1234/exeレポートが/bin/readlink。コマンドを実行すると、Bashはこの最適化を実行します。

bash -c 'readlink /proc/$$/exe`

ただし、リダイレクトがある場合はそうではありません。一部のシェル(ダッシュなど)はこの最適化を実行しません。 kshなどの一部のシェルはよりスマートで最適化されていますksh -c 'readlink /proc/$$/exe >>/root/printenvが、最適化はしませんksh -c 'readlink /proc/$$/exe; true。 (練習:なぜそれを最適化することは不可能ですか?)

関連情報