これは私にとって少し混乱しています。
次の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 コマンド処理シェルはSHELL
crontab ファイルの変数設定で定義され、デフォルトは/bin/sh
.
/bin/sh
(または互換性のあるシェル)がスクリプトを実行したときに/bin/bash -c "readlink /proc/$$/exe >> /root/printenv"
コマンドラインを解析した後のステップの1つは、変数またはコマンドの置き換えを実行することです。これには変数置換があります。つまり、$$
二重引用符で囲まれた文字列の内側です。 soを$$
プロセスのプロセスIDに置き換えます/bin/sh
。プロセスIDが1234であると仮定します。 cronによって呼び出されたシェルは/bin/bash
引数-c
とreadlink /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
。 (練習:なぜそれを最適化することは不可能ですか?)