web-dev-qa-db-ja.com

サービスユニットで/ bin / bash -cはどういう意味ですか?

再起動中にアプリを自動実行するには。

Sudo vi /etc/systemd/system/app.service

[Unit]
Description=app
After=network.target

[Service]
ExecStart=/usr/bin/python /usr/local/bin/app  
[Install]
WantedBy=multi-user.target


Sudo systemctl daemon-reload
Sudo systemctl enable app.service

これで、再起動中にアプリが自動実行されます。
アプリですべての出力情報を/var/log/app.logに書き込むようにします。
これが私がやることです。
1.Sudo touch /var/log/app.log
2。 ExecStartのみを変更します。

ExecStart=/usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1

アプリは実行できますが、/ var/log/app.logにログが書き込まれません。
ルートはアプリを実行します。
これはここでの証拠です。

ps aux|grep  app
root       246  0.0  3.8  56052 10056 ?        Ss   00:57   0:00 /usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1

Rootに/var/log/app.logにログを書き込む権限がないのはなぜですか?

ExecStartステートメントを次のように変更するには

ExecStart=/bin/sh -c '/usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1'  

問題が解決しました。
1。rootが/var/log/app.logにログを書き込む権限がないのはなぜですか?
2。/ bin/bash -cはサービス単位で何を意味しますか?

5

NOTE:古い投稿はOPの元の質問のコンテキストで書かれていましたbefore editまだ有効。

更新された回答:

ここで重要な問題は

ExecStart=/usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1

シェルが実行されていないため、>および2>&1リダイレクトはsystemdで認識されません。

これが、リダイレクトが機能するようにコマンド全体にシェルが必要な理由です。シェルの-cフラグについては、以下の古いバージョンの投稿を参照してください。


古い投稿

bashshの両方の-cフラグは同じことを意味します。引用符で囲まれたコマンドを実行します。大きな謎はありません。

実行しようとしているアプリは、-cフラグの意味が異なる場合があるため、すべてのコマンドですべてのコマンドラインフラグが同じであると想定しないでください。アプリのドキュメントがなければ、オプションが何をすべきかを伝えるのは困難です。

ここでの潜在的な問題は、pythonインタープリターが-cをアプリではなく独自のコマンドライン引数として想定することです。おそらく、それがコマンドが失敗する主な理由です。

ExecStart=/usr/bin/python /usr/local/bin/app -c /etc/app.jsonはコマンドを処理できるはずです。私は小さなスクリプトでテストしました:

$ cat test_script.py
import sys
print sys.argv[1],sys.argv[0]
$ python test_script.py this is a test                
this test_script.py

より良いアプローチ:スクリプトはSudo chmod +x /usr/local/bin/appで実行可能にし、単独で使用する必要があります。元々/ bin/sh、次にpythonで記述され、実際のスクリプトを呼び出す方法は、冗長です。私のテストスクリプトの例では、次のようになります。

$ cat test_script.py                                  
#!/usr/bin/env python
import sys
print sys.argv[1],sys.argv[0]
$ chmod +x test_script.py
$ ./test_script.py this is a test
this ./test_script.py

pythonはUbuntuのPython 2.7を指すことに注意してください。特にPython3を使用する必要がある場合は、代わりに/ usr/bin/python3を使用してください。最も好ましい方法は、アプリの最初の行に#!/usr/bin/env pythonまたは#!/usr/bin/env python3を含めることです。

2

それは許可の問題ではありません。 ExecStart文字列の実行に関与するシェルはありません。コマンドとそのコマンドに渡されるオプションのみ。リダイレクトもパイプも;との連結も、置換またはその他のシェル機能もありません。したがって、「リダイレクト」はオプションとしてアプリに渡されます(アプリがこれを処理する方法を知っているのはあなただけです)。

これを変更するには、シェルを呼び出し、コマンドとリダイレクトをコマンド文字列としてシェルに渡します。これが-cオプションの機能です。

しかし、systemdが意図したとおりにサービスとロギングを使用しない理由を考えてください。デフォルトでは、systemdユニットのstdoutとstderrはsyslogに送信されます。サービスのStandardOutput=行で設定できます。 man systemd.execをご覧ください

3
Philippos

Sudo vi /etc/systemd/system/app.service

[Unit]
Description=app
After=network.target

[Service]
ExecStart=/usr/bin/python /usr/local/bin/app  
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target

Sudo systemctl daemon-reload
sudo systemctl enable app.service

ジャーナルコマンドでアプリのログを検索するには。

Sudo journalctl  -u  app
1