Skip to content

systemdのユーザーユニットに環境変数を設定したい場合はEnvironパラメータまたはhomectlで設定する

systemdにはユーザーユニットがあってサービスプログラムを起動できるけれど、これ自体は ~/.bash_profile などのプロファイルを実行しない。なので環境変数をユニットから起動するプログラムに渡したい場合はユニットの Environment= を使うか、または homectl で設定しなければならない。

具体例でいうと、~/.bash_profileGNUPGHOME を設定した状態で gpg-agent をソケット経由で起動した場合。プロセスツリーは以下のようになる。

Terminal window
$ pstree
systemd─┬─Xwayland───4*[{Xwayland}]
├─dirmngr
├─ghostty─┬─bash───pstree
│ └─20*[{ghostty}]
├─ghostty─┬─bash
│ └─20*[{ghostty}]
└─systemd─┬─(sd-pam)
├─gpg-agent─┬─scdaemon───2*[{scdaemon}]
│ └─{gpg-agent}
└─xdg-permission-───3*[{xdg-permission-}]

ここで最上位にある systemdinit と呼ばれるPIDが1の systemd プロセスを意味する。

まず GNUPGHOME が設定されている bash プロセスだけど、これは ghostty から起動される。ghostty の親が init なところは驚いたけど、それを無視すると一般的なツリー状態だと思う。

Terminal window
$ ps lax | grep -E 'PID|ghostt'
F UID PID PPID PRI NI TIME COMMAND
0 60331 176549 1 20 0 0:23 /usr/bin/ghostty
0 60331 184679 1 20 0 0:10 /usr/bin/ghostty

そうして ghostty プロセスが GNUPGHOME 環境変数を持っている。親プロセスは init なので、ユーザーが ~/.bash_profile で設定した環境変数を知らない。なので ghostty がシェルを起動して各種プロファイルを読み込んでいるのだろう。それは environ ファイルからも読み取れる。

Terminal window
$ xargs -0 -a /proc/176549/environ -n1 echo | grep GNUPG
GNUPGHOME=~/.local/share/gnupg

gpg-agentsystemdのユーザーユニットで起動する。このとき、親プロセスは systemd —user となっている。別途確認したけどプロセス 1395 の親プロセスは init だった。

Terminal window
$ ps lax | grep -E 'PID|gpg'
F UID PID PPID PRI NI TIME COMMAND
0 60331 188107 1395 20 0 0:00 /usr/bin/gpg-agent --supervised
$ ps aux | grep -E 'PID|1395'
USER PID TIME COMMAND
lufia 1395 0:00 /usr/lib/systemd/systemd --user

このプロセスはどちらも環境変数 GNUPGHOME を持っていない。しかし homectl で設定した環境変数は持っている。

Terminal window
$ systemctl --user show-environment | grep QT_IM
QT_IM_MODULE=fcitx
$ xargs -0 -a /proc/1646/environ -n1 echo | grep QT_IM
QT_IM_MODULE=fcitx

なので、事前に環境変数をユニットへ渡したければ homectl で与えるか、明示的に Environment= パラメータで設定する必要がある。または、動的に設定したい値があるなら systemctl set-environmentsystemctl import-environment を使う。