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


162

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

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

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

回答:


197

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

これを行う現在の最良の方法は、実行することです。これ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です。

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


4
sysconfigパスはFedoraに固有のものであると思いますが、質問はArch Linuxについてです。paluhの答えはもっと面白いと思う
ルドヴィッククーティ

1
/etc/sysconfigFedora固有です。AFAIR Arch Linuxは/etc、Fedora固有の場所ではなく、パッケージ固有の場所に設定ファイルを置くことを求めていました。のように/etc/myservice.conf、ここでは余分なファイルを使用するのは正しい方法ではないようです。
ミチャウゴルニー14

5
ダメダメダメ。/ etc / sysconfigは推奨されません。debianの/ etc / default / *には意味がなく、名前は無意味であり、下位互換性の理由でのみ意味があるため、推奨されません(/ etcはすべて/ etc /だけでなく、システムの構成に関するものですsysconfig、および/ etc / defaultsはオーバーライド用であり、デフォルトではありません)。定義をユニットファイルに直接配置するか、不可能な場合は、パッケージ固有の場所を持つ環境ファイルに配置します(Michałのコメントが示唆するように)。
zbyszek

1
@FrederickNordこれは、変数と値のペアです(DJANGO_SETTINGS_MODULE=project.settings1行に1 つなど)。
マイケルハンプトン

1
@MichaelHampton「現在の最善の方法」のドキュメントリンクを追加してください。
jb。

77

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

それはあなたのローカルユニットなので、境界はかなりぼやけており、どちらの方法でも機能します。ただし、配布を開始し/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=

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


systemctl daemon-reloadコマンドはsystemdにリロードすることです
ドミトリーBuzolin

EnvironmentFile=値がパスワードのような秘密である場合に優れています。詳細については私の答えをご覧ください。
ドンカークビー


17

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

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

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

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。もちろん、独自のシステムで確認してください。


8

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

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

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

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

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

7
これは複数の理由で機能しません(「ワンショット」サービスである場合を除きますが、それはかなり無意味です)。私は以下を機能させることができました/bin/bash -a -c 'source /etc/sysconfig/whatever && exec whatever-program'-a(あなたがすべての変数の接頭辞する場合を除き性を保証は、環境がサブプロセスにエクスポートされるwhateverexport
Otheus

なぜ機能しないのですか?スクリプトの実行を含むコマンド全体を常にトリガーする必要がありますよね?
user1830432

ExecStart=/usr/bin/env ENV=script /bin/myforegroundcmdこの場合、おそらく少し良い解決策です。
kstep

@Otheus:すばらしい答えです。Tomcat8ユニットファイルを作成しなければならなかったときに保存されていました。
ダニエル

1
systemdサービスファイルで「イン」してbashコマンドを実行する方法があります。:このリンクを参照してくださいcoreos.com/os/docs/latest/...
マーク・Lakata
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.