システムサービスユニットファイルに環境変数を動的に割り当てる方法はありますか?
4つのGPUを持つマシンがあり、各GPUがサービスの複数のインスタンスを起動したいと考えています。たとえば、
- gpu_service@1:1.service
- gpu_service@2:1.service
- gpu_service@3:1.サービス
- gpu_service@4:1.サービス
- gpu_service@1:2.service
- gpu_service@2:2.service
- gpu_service@3:2.service
- gpu_service@4:2.service
- 嫌な
したがって、1:1、2:1などは実際にはサービス単位ファイルの%iです。
サービスを特定のGPUにバインドするために、サービス実行可能ファイルは特定の環境変数をチェックします。たとえば、次のようになります。
USE_GPU=4
サービス単位ファイルから%iを取得し、いくつかの(シェル)関数を介して実行してGPU番号をエクスポートし、それに応じてUSE_GPU環境変数を設定する方法はありますか?
/etc/systemd/system/gpu_service@x:y.service/local.conf
最も重要なのは、より多くのインスタンスを起動するために複数のファイルを作成する手間がかからないことです。
答え1
注意が必要な場合は、インスタンスサービスファイルに小さなbashスクリプトシーケンスをexecコマンドに統合できます。例えば
ExecStart=/bin/bash -c 'v=%i; USE_GPU=$${v%:*} exec /bin/mycommand'
$$
文字列はbashに渡された結果では単一になりますが、もっと重要なのはsystemdによる補間が$
停止されることです。${...}
(以前のバージョンのsystemdには文書化された使用法がなかった$$
ため、その時点でサポートされていたかどうかはわかりません。)
答え2
組み込みの方法はありません。サービスが開始される前に、これらのタスクを実行する必要があります。一つの方法は環境ファイルに入れることです。
[Service]
# Note you need to escape percentage sign
ExecStartPre=/bin/sh -c "my_awesome_parser %%i > /run/gpu_service_%i"
EnvironmentFile=/run/gpu_service_%i
ExecStart=...
答え3
実際、systemdユニットファイルで環境変数を設定できるようです。
コメント作成者が提案したように、解決策は次のとおりです。
システム単位での環境変数の使用
環境ガイドライン
systemd には、実行プロセスの環境変数を設定する環境ディレクティブがあります。スペースで区切られた変数割り当てのリストが必要です。このオプションは複数回指定できます。この場合、リストされているすべての変数が設定されます。同じ変数を2回設定すると、後の設定は以前の設定を上書きします。このオプションに空の文字列を割り当てると、環境変数のリストがリセットされ、以前の割り当てはすべて適用されません。環境ディレクティブは、etcd2 や flannel などの組み込み Container Linux システムデバイスで使用されます。
次の例では、暗号化を使用するように etcd2 デーモンを構成できます。 etcd2.serviceの
/etc/systemd/system/etcd2.service.d/30-certificates.conf
ドロップインを作成します。[Service] # Client Env Vars Environment=ETCD_CA_FILE=/path/to/CA.pem Environment=ETCD_CERT_FILE=/path/to/server.crt Environment=ETCD_KEY_FILE=/path/to/server.key # Peer Env Vars Environment=ETCD_PEER_CA_FILE=/path/to/CA.pem Environment=ETCD_PEER_CERT_FILE=/path/to/peers.crt Environment=ETCD_PEER_KEY_FILE=/path/to/peers.key
次に、新しい環境を実行し、
sudo systemctl daemon-reload
etcd2sudo systemctl restart etcd2.service
デーモンに適用します。
引用されたテキストは、次のURLから取得されました。 https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html
答え4
EnvironmentFile
変数を含むenvファイルを指すディレクティブを使用します。このファイルは、ExecStartPre
実際のサービスが開始される前に命令によって生成されます。ExecStart
ディレクティブ内で変数にアクセスできます${GPU_COUNT}
。
[Unit]
Description=Dynamic variables in systemd units
[Service]
Type=simple
EnvironmentFile=-/tmp/gpu.env
ExecStartPre=sh -c 'printf "%%s\n" GPU_COUNT=$( (...) ) > /tmp/gpu.env'
ExecStart=(...)
ExecStartPost=sh -c 'rm /tmp/gpu.env'
file path プレフィックスを付ける必要があります-
。これにより、systemdは初期チェック中にファイルが存在しないことを無視します。後で、このExecStartPre
コマンドはenvファイルを生成します。もう一つデバイスステータスファイルの場所は再評価され(まだ以前でもExecStart
)、systemdは変数がある場合はその変数をロードします。man systemd.exec
説明は次のとおりです。
The files listed with this directive will be read shortly before the process is executed (more specifically, after all processes from a previous unit state terminated. This means you can generate these files in one unit state, and read it with this option in the next. The files are read from the file system of the service manager, before any file system changes like bind mounts take place).