systemd无法导入$ SSH_AUTH_SOCK等环境变量

问题描述 投票:1回答:2

我在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)是如此困难。

任何答案都非常欢迎。

谢谢Falk

service emacs environment gnupg systemd
2个回答
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))

0
投票

你的例子有一个拼写错误,你需要的环境变量是SSH_AUTH_SOCK而不是SSH_AUTH_SOCKET。此外,您的ExecStartPre将作为ExecStart所在环境的一部分运行,因此您无法在那里使用import。

我能够通过查找套接字文件,使用ssh-find-agent中的示例在systemd用户服务管理器中设置SSH_AUTH_SOCK。这不是防弹的,但到目前为止似乎对我有用。另外请记住,使用import-environment或set-environment将启用所有服务的值,或者在本例中为所有用户服务(因为--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单元中尝试时不起作用)

© www.soinside.com 2019 - 2024. All rights reserved.