从 systemd 使用 tmux 时避免出现“嵌套会话”警告

从 systemd 使用 tmux 时避免出现“嵌套会话”警告

我想使用一个脚本启动 2 个会话,一个守护进程会话和一个用户会话。我希望该脚本在启动时启动,无需任何用户登录。

我创建的脚本在直接启动时可以工作,但在以 root 身份使用 systemctl start daemon.service 启动时(启动时也是如此)只能部分工作。

本质上,该脚本执行以下操作:

# Clean up any old tmux sessions
tmux kill-session -t daemon > /dev/null 2>&1 
tmux kill-session -t user > /dev/null 2>&1 
rm -rf /tmp/tmux-`id -u`

tmux new-session -d -s daemon
tmux send-keys "$DAEMON" C-m

# Start the main tmux session from which we'll create 
#  all window panes 
export TMUX=
export TERM=xterm
tmux new-session -d -s user
tmux list-sessions >> $LOG

# Various window setup using "tmux split-window -h" 
#  or "tmux split-window -v" - no other args

# Window panes created. Now wait for daemon process to open socket, then
echo "Daemon is now listening." >> $LOG

tmux send-keys -t 1 "$CMD1" C-m
echo "Sent $CMD1 to pane 1" >> $LOG
tmux send-keys -t 1 "$CMD2" C-m
echo "Sent $CMD2 to pane 2" >> $LOG
...

# Spin in a loop until the daemon process stops listening, then exit

就是这样。很简单。没有嵌套会话,尽管 tmux 仍然会发出警告。为什么?我在其他地方读到,设置 TERM 并取消设置 TMUX 环境变量对于 systemd 进程是必要的,因为没有 tty 供 tmux 使用。这似乎确实有帮助,尽管我已经尝试了很多次,无法给你任何细节。

症状是两个会话都启动了,守护进程看起来正常,但用户会话窗格是空的,但所有窗格都正确创建。发送键似乎没有发送给它们,但日志看起来很完美,没有任何地方挂起。

我需要它能够在 tmux 1.9 到 2.1 的不同版本(ubuntu 16.04 和 Debian 8.7 和 8.8)上运行。用户部分启动一个“less”分页器来查看守护进程日志,以及 2 个可以与用户交互的进程。我在 .profile 中放置了一个“tmux attachment-session -t user”,这样当我登录时,我就可以看到所有窗口并可以与它们交互。即使没有用户,用户进程也必须从守护进程启动,这一点很重要。

我不明白为什么 tmux 似乎认为会话是嵌套的,因为 2 个会话是从同一个脚本启动的。当脚本退出时,会出现问题,然后 systemd 将再次调用该脚本来重新启动所有内容。为了测试,我确实注释掉了 #Restart=on-failure。

通过查看 ps,我可以看到 send-keys 正在执行,它们都在运行。我认为 TMUX 和 TERM 环境变量是问题的关键,但我不确定如何解决它,因此 A) tmux 分离会话,B) 在没有用户或打开终端 tty 的情况下启动没有问题。

答案1

这真是个兔子洞,需要花很多时间才能弄清楚。在我看来,systemd/OS 实现者有几个问题需要解决。我不确定 Ubuntu 的情况,但 Debian 8.8 肯定需要注意。

有了我将在此处提供的信息,获得一个有效的设置应该不难。但请注意,对于为什么 tmux 会感到困惑并将上述内容视为“嵌套”会话,我无法给出具体答案。

这个问题是在尝试在启动时自动启动守护进程和 tmux 脚本时出现的。我尝试使用一个脚本来完成所有操作,然后出现了这个 tmux“多会话”问题。

我的最终解决方案是将守护进程和 tmux 窗口的启动分为两个独立的进程,均由 systemd 自动执行。我选择使用“系统”systemd 单元来启动守护进程,使用“会话”单元来启动 tmux 脚本。虽然我还没有尝试将守护进程和 tmux 脚本都放在用户会话 systemd 单元中,但我相信这样做不会有问题。这种分离有其优点,这里就不多说了。

弄清楚如何在非 X-windows、仅 tty 的服务器上使用 systemd 用户会话单元花费了大部分精力。以下是基本步骤:

1) 以 root 身份运行apt-get install libpam-systemd。在我使用过的某些 Debian 8.8 系统上,即使在执行 之后,这也是必要的apt-get update。这会在用户登录时建立 DBus 会话范围和 systemd 用户进程管理器,包括重要的环境变量。不幸的是,并非所有重要变量都已设置,这就是 Debian 操作系统需要修复的问题。

2) 如果您希望在启动时启动用户会话,以便用户无需登录,并希望它在重新启动后继续存在,请以 root 身份执行loginctl enable-linger <user account name>。这将启用[电子邮件保护]systemd 进程即使在所有登录会话关闭后仍会保留,并会在系统启动时自动启动。

3) 不幸的是,Debian 8.8 中重要的环境变量设置不正确,需要修复,但这并不难。在用户的 .profile 或 .bashrc 脚本中,添加: export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/systemd" 您应该能够检查/run/user/$UID/包含用于用户会话 DBus 通信的套接字的尾部文件夹。在 Debian 8.8 上,即“systemd”。

请注意,您可能需要重新启动才能使所有 systemd 单元按顺序正确初始化。如果您export在不带参数的情况下执行,您应该会看到 XDG_RUNTIME_DIR="/run/user/ id -u" 和 XDG_SESSION_ID 设置为某个值。如果没有,则您的 systemd 用户会话仍然存在问题。如果您通过 ssh 登录,请检查您的 /etc/ssh/sshd_config 是否已UsePAM设置为 yes,以便执行 libpam-systemd 代码。

我怀疑与 libpam-systemd 关联的 systemd 单元需要更新,以便它们设置当前缺失的所有环境变量。也许可以通过取消注释DefaultEnvironment=并将其设置为 来 修复 /etc/systemd/user.conf 中的错误DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/systemd",但我不确定这是否有效。

以下是一些可能对您有帮助的链接:1:7.10. Systemd 的使用和配置 2:从命令行检查 D-Bus 3:使用 systemd 管理会话

相关内容