特定のイベントのためにシステムデーモンによって実行される短いスクリプトがあります。イベントが発生し、スクリプトが実行されていることはわかっていますが、意図したとおりに動作しません。不思議なことに、それを手動で実行するとそうなるので、非常に混乱しています。
何が起こっているのか、どうすればわかりますか?スクリプトは基本的に次のような一連のコマンドです。
/bin/foo on 3
sudo bar a
特定のイベントのためにシステムデーモンによって実行される短いスクリプトがあります。イベントが発生し、スクリプトが実行されていることはわかっていますが、意図したとおりに動作しません。不思議なことに、それを手動で実行するとそうなるので、非常に混乱しています。
何が起こっているのか、どうすればわかりますか?スクリプトは基本的に次のような一連のコマンドです。
/bin/foo on 3
sudo bar a
回答:
まず、スクリプトがシステムデーモンによって実行され、そのデーモンがroot権限で実行されている場合、を使用する必要はありませんsudo
。これにはinit
(およびsystemd
)が含まれ、これにはが含まれrc.local
ます。そのデーモンがされている場合ではない root権限で実行している場合、sudo
しない限り動作しません/etc/sudoers
ように(パスワードなし)を許可するように設定されています。Raspbianユーザーはpi
、デフォルトで何でもできるようになっているため、混乱する可能性があります(また、調べてみると、/etc/sudoers
それがどのように行われるかがわかります)。
次に、次のbash
ようなサブシェルで実行することにより、bashスクリプト内の任意のスクリプトまたはコマンドセットからの出力をキャプチャできます。1
(
/bin/foo on 3
sudo bar a
) &> /var/log/myTestLog.txt
()
示しサブシェルを。この中にあるものからのすべての出力は、/var/log/myTestLog.txt
ファイルにリダイレクトされています。いくつかのメモ:
&>
はバシズムです。したがって、スクリプトが最初の行のシバンを介して実行される場合、それは#!/bin/bash
だけでなくである必要があります/bin/sh
。「バシズム」はbash
シェルでのみ機能します。
これには/etc/rc.local
、デフォルトで使用されるが含まれます/bin/sh
(つまり、はい、これをに安全に変更できます/bin/bash
)。
/var/log
書き込みにはroot権限が必要です。プロセスにそのようなものがない場合は、使用できることがわかっているディレクトリを使用または作成します。確信が持てない場合、システムをシャットダウンまたは再起動せずにこれをテストできる場合/tmp
は、誰でも(つまり誰でも)書き込み可能なを使用してください。ただし、/tmp
ブート間で持続しません。また、RAMベースの小さなパーティションであるため、ギグのデータを書き込まないでください。それはあなたのSDカードではありません[実際にはRaspbianの現在のバージョンではありますが、実際にはこれを当てにしないでください]。
&>
内のすべてが上書きされmyTestLog.txt
ます。代わりに、既存のログに追加したい場合は、デバッグ目的に適している可能性があります&>>
。次に、次のようにそのサブシェルの先頭にコマンドを追加できます。
echo Starting $(date)
各実行から情報を分離するため。これが何をするかわからない場合は、コマンドラインで試してください。
この最後の点は、何も出力しないコマンドに関して実行できることの良い例ですが、それらのほとんどは、たとえば-v
「verbose」を含めた場合に実行できます。一部のコマンドに-v
は「バージョン情報を印刷する」という意味があります。コマンドのmanページを見て、これが機能するかどうか、およびどのように機能するかを確認してください(一部のコマンドは、とは異なるスイッチも使用しています-v
)。
慣例により、コマンドは完了すると値0を返します。これは「終了ステータス」と呼ばれることもあり、通常は表示されませんが、シェルではが表示されますecho $?
。やってみる
ls /
echo $?
ls /nonexistantdir
echo $?
0と2が表示されます。その後ls
、「終了ステータス」の下のmanページを見ると、かなり具体的ではない、謎めいていることがわかります。
2 if serious trouble (e.g., cannot access command-line argument).
それは何よりも良いかもしれないしそうでないかもしれませんが、あなたはそこに行きます。
少なくとも、何らかの理由でコマンドが失敗したことを示しています。終了ステータスでは、次のようなこともできます。
/bin/foo && sudo bar
&&
「最初のコマンドが成功した場合、」この場合の手段では、最初のコマンドを想定すると、(彼らは通常行う理由である)0を返すの規則を使用しています。/bin/foo
が機能しない、見つからないなどの場合は、sudo bar
発生しません。
ロギングメッセージと条件付き実行(&&
)を組み合わせて使用すると、問題の把握に近づくか、少なくとも問題の解決に役立つ他の人に役立つ情報を取得できます。 それがなければ、他の誰もができることのほとんどは推測です。
1.次を使用して、スクリプト全体に対して同じ出力リダイレクトを内部から実行できます。
exec &> /var/log/myTestLog.txt
上部(または任意の場所、それ以降のすべてに適用されます)。
デーモンとしてスクリプトを実行するとき、人々が忘れがちな1つの重要な側面は、シェル環境、$PATH
特に変数です。あなたの例では、2行目$PATH
はsudo
is の完全な名前に依存してい/usr/bin/sudo
ます。ユーザーシェルは、/usr/bin
実行可能ファイルを検索するときに検索するように指示されているため、それだけを知っています。同じことがにも当てはまりますbar
。
sudo
スクリプトをデーモンとして実行する場合は必要ないことを考えると、2行目は次のようになります。
/path/to/bar a
U&L
ます。タイトルを誤解しており、「デバッグのためにシステムスクリプトの出力をログに記録する」ことで目的がより明確になるとお勧めします。また、これらのfoo
bar
例を読んだとき、私の脳は凍りつき、より現実的な世界に見えるものが好きです。投稿を編集するのは気が進まないので、改善できると思われる場合は、このままにしておきます。