我在systemd的用户空间写了一个服务文件,用于启动emacs守护进程。这非常有效。但是在启动emacsclient时,我让解密我的日记文件。为此我运行了gpg-agent。通常当emacs启动时,会弹出pineentry-gtk并提示我输入我的私钥密码。但是使用systemd启动了守护进程环境变量$ SSH_AUTH_SOCKET,$ GPG_AGENT_INFO和SSH_AGENT_PID是未知的。因此没有pineentry-gtk弹出。从系统arround进给系统的几种方法被卡住了。我想使用动态方法而不是放入绝对路径。
我定义了一个systemd EnvironmentFile并放入
SSH_AUTH_SOCKET=${SSH_AUTH_SOCKET}
并将该文件包含在emacs.sevice中。在这里调查我发现了 this链接,无法想象这是真的。这意味着服务/单元文件中的环境设置是在环境文件中设置它的另一个故事。他们无法相见。什么意义使得环境文件?
下一步是从登录时间我的源代码〜/ .bash_profile导入环境变量。
systemctl --user import-environment GPG_AGENT_INFO
systemctl --user import-environment SSH_AUTH_SOCKET
systemctl --user import-environment SSH_AGENT_PID
登录后我看了一下是为了看看systemd是否得到了环境变量。我通过输入
得到了这个systemctl --user show-environmet
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
GPG_AGENT_INFO=${GPG_AGENT_INFO}
HOME=/home/xxxx
LANG=de_DE.UTF-8
LOGNAME=xxxx
PATH=/home/xxxx/bin:~/.emacs.d/shell-scripts: .........
AUTH_SOCK=${SSH_AUTH_SOCKET}
USER=xxxx
XDG_RUNTIME_DIR=/run/user/1000
但是在systemd环境中启动emacs守护程序会向我显示相同的症状。
下一步是直接在单位/服务文件中导入变量,如下所示。
[Unit]
Description=Emacs: the extensible, self-documenting text editor
[Service]
# loading default environment for systemd in user space
EnvironmentFile=%h/.config/systemd/xxxx-default-evironment.env
Type=forking
ExecStartPre=/bin/systemctl --user import-environment SSH_AUTH_SOCKET
ExecStart=/usr/bin/emacs --daemon
ExecStartPost=/bin/systemctl --user set-environment SSH_AUTH_SOCK=${SSH_AUTH_SOCK}
ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)"
Restart=always
[Install]
WantedBy=non-graphical.target
这种方法也没有成功。顺便说一下,不能相信将 SYSTEM 的一些环境变量发布到 SYSTEM(D)是如此困难。
非常欢迎任何答案。
由于 福克
答案 0 :(得分:1)
这是一个很好的实用程序,称为keychain,它将启动一个ssh-agent / gpg-agent,然后将env vars转储到一个文件中。 Shell可以只获取文件来获取变量,而其他程序(如Emacs)可以解析文件以获取变量。对于Emacs,Melpa中有一个钥匙串环境包。
# .bash_profile
type keychain >&/dev/null \
&& keychain --agents ssh
# .bashrc
[ -f $HOME/.keychain/$HOSTNAME-sh ] \
&& . $HOME/.keychain/$HOSTNAME-sh
;; init.el
(when (require 'keychain-environment nil 'noerror)
(keychain-refresh-environment))
答案 1 :(得分:0)
您的示例有一个错字,您需要的环境变量是SSH_AUTH_SOCK而不是SSH_AUTH_SOCKET。另外,您的ExecStartPre将与ExecStart在同一环境中运行,因此您不能在其中使用导入。
我能够使用ssh-find-agent中的示例通过找到套接字文件在systemd用户服务管理器中设置SSH_AUTH_SOCK。这不是防弹,但到目前为止对我来说似乎很好。还要记住,使用import-environment或set-environment将启用ALL服务的值,在这种情况下,将启用所有用户服务的值(由于--user)。如果您不希望这样做,最好将逻辑移入包装脚本并直接执行,而不是直接执行服务。
以下是将sshfs用作systemd用户服务单元的一部分的示例:
# Create mount directory and make sure user has correct permissions
sudo mkdir /mnt/myserver
sudo chown $USER:$USER /mnt/myserver
# Create the following file:
systemctl --user cat sshfs-myserver.service
# /home/USERNAME/.config/systemd/user/sshfs-myserver.service
[Unit]
AssertPathExists=/mnt/myserver
[Service]
Type=forking
ExecStartPre=/bin/bash -c "systemctl --user set-environment SSH_AUTH_SOCK=$(find /tmp/ -type s -name agent.* 2> /dev/null | grep -o '/tmp/ssh-.*/agent.*')"
ExecStart=/usr/bin/sshfs -o sshfs_debug root@myserver:/ /mnt/myserver
Restart=no
[Install]
WantedBy=default.target
# Then enable service, run, and check status/env
systemctl --user enable ssh-myserver
systemctl --user daemon-reload
systemctl --user start sshfs-myserver
systemctl --user show-environment
systemctl --user status sshfs-myserver
通常,您只需要使用带有Type=fuse.sshfs的systemd挂载单元,但是它们似乎需要以root用户身份运行mount命令(当我在--user单元中尝试时不起作用)