tmux服务器调用daemon(3)将自己与启动它的进程(即初始tmux客户端)分离。这不是可选的,因此在daemon(3)完成双分叉和中间退出之后,服务器将始终重新设置为 PID 1(例如init ) 。
一般来说,tmux服务器不再直接“连接”到gnome-session虽然是(幸存的)进程的父级,但这并不重要。
在ssh的情况下,无需重新输入密码即可使用密钥的能力依赖于对ssh-agent进程的访问。ssh实例查找 SSH_AUTH_SOCK 环境变量以了解在哪里联系可以为其提供密钥的ssh 代理。gnome-session可能会安排启动ssh-agent并使用适当的 SSH_AUTH_SOCK 值填充其环境。当您启动各种进程时,此环境会从父级继承到子级。这样,tmux服务器也会继承 SSH_AUTH_SOCK 值(从最初的tmux客户端,它从一个 shell 中获取它,它从gnome-terminal,它是从gnome-session获得的)。
但是,当您附加到从不同环境启动的tmux会话时,就会出现问题。考虑以下场景,这暗示了tmux服务器的 PID 低于gnome-session的 PID :
- 登录到 GUI 会话。
gnome-session启动一个ssh-agent并SSH_AUTH_SOCK=foo
在其环境中进行配置;该值将由其所有未来的子代继承。
- 您启动一个tmux服务器(通过 shell 和gnome-terminal)。tmux服务器继承
;它将被传递给它的子进程(例如,在tmux会话中运行的 shell)。SSH_AUTH_SOCK=foo
- 您从tmux会话断开连接并注销您的 GUI 会话。tmux服务器及其子节点仍然具有,但
该值可能不再有效(当gnome-session结束时,它可能会杀死它启动的ssh-agent )。SSH_AUTH_SOCK=foo
- 稍后,您重新登录到 GUI 会话。
这次gnome-session设置SSH_AUTH_SOCK=bar
并将其传递给它的孩子。
- 您重新连接到您的tmux会话。
此时,您拥有SSH_AUTH_SOCK=bar
“外部” tmux和SSH_AUTH_SOCK=foo
“内部”会话。这可能是您遇到问题的地方。
实际上,由于tmux服务器已经超过了原始 GUI 会话,因此它最初继承的任何特定于该会话的环境变量都可能无效(除非它们碰巧在您下次登录 GUI 会话时使用完全相同的值)。
幸运的是,tmux具有处理这种情况的功能。session 选项指定了一个环境变量列表,当客户端创建或附加到会话时,这些update-environment
环境变量会被复制到“会话环境”中(或从中删除)。SSH_AUTH_SOCK 是此选项默认值的一部分,因此在您重新附加时会更新。但是,tmux只能更新它的“会话环境”(它将被该会话的任何新子代继承)。
不幸的是,tmux无法更新属于该会话的任何现有进程(事实上,这是不可能的,缺少可以修补已运行进程内部的调试工具)。因此,在上述情况之后在 Windows/窗格中运行的任何现有 shell 都可能使用无效的 SSH_AUTH_SOCK。ssh不会抱怨无效值,它只会提示您输入适当的密钥密码。
您可能会尝试做的是从会话环境中提取 SSH_AUTH_SOCK 的值,并使用如下命令将其合并到旧会话中预先存在的 shell 中:
SSH_AUTH_SOCK=$(tmux show-environment | awk '/^SSH_AUTH_SOCK=/ { sub(/.*=/,""); print }')
If you are having issues related to other environment variables, then you may need to add them to update-environment
(e.g. set-option -ga update-environment ' FROBNIZ'
in your ~/.tmux.conf
) and do something similar to copy the values into any existing shells after you reattach from a different context.