web-dev-qa-db-ja.com

systemdサービスで環境変数を設定する方法は?

systemdを使用したArch Linuxシステム を使用しており、独自のサービスを作成しました。 /etc/systemd/system/myservice.serviceの構成サービスは次のようになります。

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

次に、/bin/myforegroundcmdに環境変数を設定します。それ、どうやったら出来るの?

188
lfagundes

時代は変わり、ベストプラクティスも変わります。

current これを行う最良の方法は、systemctl edit myserviceを実行することです。これにより、オーバーライドファイルが作成されます。既存のものを編集できます。

通常のインストールでは、これによりディレクトリ/etc/systemd/system/myservice.service.dが作成され、そのディレクトリ内に名前が.confで終わるファイル(通常はoverride.conf)が作成されます。このファイルに追加または上書きできます配布によって出荷されたユニットの任意の部分。

たとえば、ファイル/etc/systemd/system/myservice.service.d/myenv.confの場合:

[Service]
Environment="SECRET=pGNqduRFkB4K9C2vijOmUDa2kPtUhArN"
Environment="ANOTHER_SECRET=JP8YLOc2bsNlrGuD6LVTq7L36obpjzxd"

また、ディレクトリが存在し、空の場合、サービスは無効になります。ディレクトリに何かを配置するつもりがない場合は、それが存在しないことを確認してください。


参考までに、古い方法は:

推奨される方法 これを行うには、変数を含むファイル/etc/sysconfig/myserviceを作成し、それらをEnvironmentFileでロードします。

詳細については、Fedoraのドキュメント systemdスクリプトの記述方法 を参照してください。

232
Michael Hampton

答えは、変数が定数である(つまり、ユーザーがユニットを取得することによって変更されることを想定していない)か、変数(ユーザーが設定したと想定される)であるかによって異なります。

ローカルユニットであるため、境界はかなりぼやけており、どちらの方法でも機能します。ただし、配布を開始して/usr/lib/systemd/systemになる場合は、これが重要になります。

定数値

インスタンスごとに値を変更する必要がない場合は、ユニットファイルに直接Environment=として配置することをお勧めします。

[Unit]
Description=My Daemon

[Service]
Environment="FOO=bar baz"
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

その利点は、変数がユニットと共に単一のファイルに保持されることです。したがって、ユニットファイルはシステム間を移動する方が簡単です。

変数値

ただし、sysadminが環境変数の値をローカルで変更することになっている場合、上記のソリューションはうまく機能しません。具体的には、ユニットファイルが更新されるたびに新しい値を設定する必要があります。

この場合、追加のファイルが使用されます。方法—通常は配布ポリシーによって異なります。

特に興味深い解決策の1つは、/etc/systemd/system/myservice.service.dディレクトリを使用することです。他のソリューションとは異なり、このディレクトリはsystemd自体でサポートされているため、ディストリビューション固有のパスはありません。

この場合、/etc/systemd/system/myservice.service.d/local.confのようなファイルを配置して、ユニットファイルの不足している部分を追加します。

[Service]
Environment="FOO=bar baz"

その後、systemdはサービスの開始時に2つのファイルをマージします(どちらかを変更した後はsystemctl daemon-reloadに注意してください)。また、このパスはsystemdによって直接使用されるため、EnvironmentFile=を使用しないでください。

影響を受けるシステムの一部でのみ値が変更されることになっている場合は、両方のソリューションを組み合わせて、ユニットに直接デフォルトを指定し、他のファイルにローカルオーバーライドを指定できます。

80
Michał Górny

http://0pointer.de/public/systemd-man/systemd.exec.html#Environment= -2つのオプションがあります(1つはMichaelがすでにポイントしています):

Environment=

そして

EnvironmentFile=
42
paluh

Michael および Michał による回答は役に立ち、systemdサービスの環境変数を設定する方法についての元の質問に回答します。ただし、環境変数の 一般的な使用 の1つは、パスワードなどの機密データを、アプリケーションのコードで誤ってソース管理にコミットされない場所に構成することです。

そのため、サービスに環境変数を渡したい場合は、しないでくださいユニット構成ファイルでEnvironment=を使用します。 EnvironmentFile=を使用して、サービスアカウント(およびrootアクセス権を持つユーザー)のみが読み取り可能な別の構成ファイルを指定します。

ユニット構成ファイルの詳細は、次のコマンドですべてのユーザーに表示されます。

systemctl show my_service

私は/etc/my_service/my_service.confに構成ファイルを置き、そこに私の秘密を置きます:

MY_SECRET=correcthorsebatterystaple

次に、サービスユニットファイルでEnvironmentFile=を使用しました。

[Unit]
Description=my_service

[Service]
ExecStart=/usr/bin/python /path/to/my_service.py
EnvironmentFile=/etc/my_service/my_service.conf
User=myservice

[Install]
WantedBy=multi-user.target

ps auxeがこれらの環境変数を表示できないこと、および他のユーザーが/proc/*/environにアクセスできないことを確認しました。もちろん、あなた自身のシステムをチェックしてください。

18
Don Kirkby

マイケルは1つのクリーンなソリューションを提供しましたが、スクリプトから更新されたenv変数を取得したいと思いました。 systemdユニットファイルでは、残念ながらbashコマンドを実行できません。さいわい、ExecStart内でbashをトリガーできます。

http://www.dsm.fordham.edu/cgi-bin/man-cgi.pl?topic=systemd.service&ampsect=5

この設定はシェルコマンドラインを直接サポートしないことに注意してください。シェルコマンドラインを使用する場合は、何らかのシェル実装に明示的に渡す必要があります。

この場合の例は次のとおりです。

[Service]
ExecStart=/bin/bash -c "ENV=`script`; /bin/myforegroundcmd"
8
user1830432