如何在SSH会话上自动启动tmux?

Ale*_*yan 68 ssh tmux

我有十台左右的服务器,我定期用SSH连接.每个人都在我的本地计算机~/.ssh/config文件中有一个条目.

为了避免在我的Internet连接不可避免地丢失时失去对正在运行的进程的控制,我总是在tmux会话中工作.我希望有一种方法可以在每次启动SSH连接时自动连接tmux,因此我不必在SSH连接tmux attach || tmux new后始终输入.

不幸的是,这并不像我原先希望的那么简单.

  • 我不想~/.bashrc在服务器上添加任何命令,因为我只希望它用于SSH会话,而不是本地会话.
  • 添加tmux attach || tmux new~/.ssh/rc服务器上只会导致not a terminal连接后抛出错误,即使RequestTTY force在我的本地SSH配置文件中将该选项添加到该服务器的行中也是如此.

小智 72

服务器端配置:

要在通常通过SSH(并且只有SSH)登录时自动启动远程服务器上的tmux,请相应地编辑~/.bashrc远程服务器上的用户或root用户(或两者):

if [[ -n "$PS1" ]] && [[ -z "$TMUX" ]] && [[ -n "$SSH_CONNECTION" ]]; then
  tmux attach-session -t ssh_tmux || tmux new-session -s ssh_tmux
fi
Run Code Online (Sandbox Code Playgroud)

ssh_tmux如果不存在,则此命令将创建一个调用的tmux会话,或者重新连接到具有该名称的现有会话.如果您的连接丢失或几周前忘记了一个会话,每次SSH登录都会自动返回您留下的tmux-ssh会话.

从您的客户连接:

没什么特别的,只是ssh user@hostname.

  • 我正在寻找这个,我前段时间使用了一段非常类似的代码,但会话是用户名(将`ssh_tmux`改为`$ USER`) (4认同)
  • 请参阅moneytoo的[答案](/sf/answers/3067381831/),以获取有关`$ SSH_TTY`与`$ SSH_CONNECTION`的有用评论. (3认同)
  • 为了避免破坏“ scp”,您还需要检查这是否是交互式外壳程序:`if [[-n“ $ PS1”]] && [[-z“ $ TMUX”]] && [[-n“ $ SSH_CONNECTION“]]; ` (3认同)
  • @janfrode 不要依赖 `$PS1`,而是使用 `[[ $- == *i* ]]` ,因为即使 PS1 不是交互式 shell,也可以定义它。 (3认同)
  • 您可以使用 `tmux new-session -A -s ssh_tmux` 替换 `tmux attach-session -t ssh_tmux || tmux new-session -s ssh_tmux` 更短,如果有点混乱,`-A` 告诉 tmux 附加会话,如果它已经存在 (2认同)

Ale*_*yan 45

好吧,我找到了一个满意的解决方案.在我的本地~/.bashrc,我写了一个函数:

function ssh () {/usr/bin/ssh -t $@ "tmux attach || tmux new";}
Run Code Online (Sandbox Code Playgroud)

它基本上覆盖了ssh终端函数,用给定的参数调用内置的ssh程序,然后是"tmux attach || tmux new".

($@表示命令行上提供的所有参数,因此ssh -p 123 user@hostname将扩展为ssh -t -p 123 user@hostname "tmux attach || tmux new")

(该-t参数等同于RequestTTY Forcetmux命令并且是必需的.)

  • 如果您的`tmux`版本支持它,请考虑使用`tmux new -A foo`,如果可能的话,它将附加到名为`foo`的现有会话,必要时创建它.这可以让你将函数简化为`/ usr/bin/ssh -t"$ @"tmux new -A`(并且一定要引用`$ @`!). (19认同)
  • 注意:如果你经常连接的一些机器没有安装tmux,你可能想说`function ssht`之类的,这样你就可以继续正常使用`ssh`。否则,只要连接到没有 tmux 的机器,就在命令提示符下输入 `/usr/bin/ssh` :) (2认同)
  • 如果你很懒,你可以使用 [ssht](https://github.com/brejoc/ssht) 连接到远程 tmux 会话。OS X 用户可以[通过brew点击它](https://github.com/brejoc/homebrew-tap),Linux用户可以通过[fpm](https://github.com/jordansissel/fpm/wiki创建包) )使用此 [Makefile](https://github.com/brejoc/ssht/blob/master/Makefile) 或只需将 `ssht` 复制到 `~/bin` 即可。 (2认同)
  • 已解决: `ssh -t user@hostname "LANG=$LANG tmux Attach || tmux new"` (2认同)

Six*_*ive 40

不要在服务器端这样做!

相反,使用~/.ssh/config像这样:

远程机器上的 tmux 3.1 或更新版本¹

进入你的本地~/.ssh/config,put²:

Host myhost
  Hostname host
  User user
  RequestTTY yes 
  RemoteCommand tmux new -A -s foobar
Run Code Online (Sandbox Code Playgroud)
  • 而不是RequestTTY yes你可以ssh-tswitch调用;谢谢你,@kyb。
  • 题外话,但如果您正在处理非 ASCII 字符,我建议将其更改tmux -u …为显式启用 Unicode 支持,即使在没有设置正确环境变量的机器上也是如此。

远程机器上的 tmux 3.0a 或更早版本

与上面几乎相同,但将最后一行更改为³:

  RemoteCommand tmux at -t foobar || tmux new -s foobar
Run Code Online (Sandbox Code Playgroud)

¹截至 2021 年 7 月 28 日,随 tmux 3.1 或更新版本一起提供的发行版列表已经很长了(请参阅repology.org了解为什么发行版提供的版本)。在这一点上,人们可能真的应该推动旧版本或过时版本的更新。

²newnew-session.

³at是 的缩写attach-session


仅当出于某种原因,您真的无法在客户端执行此操作时:

使用远程authorized_keys文件

如果您~/.ssh/config出于某种原因不想拥有文件,或者希望远程机器强制连接机器连接到/打开会话,请将其添加到您的远程~/.ssh/authorized_keys

command="tmux at -t foobar || tmux new -s foobar" pubkey user@client
Run Code Online (Sandbox Code Playgroud)

当然,这将适用于所有安装了相应私钥的客户端,有些人可能认为这是一个好处 ––但是:如果出现任何问题,如果没有(半)物理访问机器,则可能无法再连接!

  • 恕我直言,这应该是投票最多的答案。我正在寻找(2)。 (2认同)
  • 这适用于独立服务器,但不幸的是,当与“Host *”一起使用时,它会使“git push”(使用 ssh)停止工作:“无法执行命令行和远程命令。” 致命:无法从远程存储库读取。` (2认同)

Den*_*din 16

连接:

ssh user@host -t "tmux new-session -s user || tmux attach-session -t user"
Run Code Online (Sandbox Code Playgroud)

会议期间:

使用Ctrl+d完成会话(TMUX窗口关闭)或Ctrl+b d临时分离从会议和以后再次连接到它.

记得!如果您的服务器重启会话丢失了!

当您在tmux中时,您可以使用它Ctrl+b s来查看会话列表并将当前切换到另一个列表.

修复你的.bashrc:

我建议你在你的下面定义通用功能.bashrc:

function tmux-connect {
    TERM=xterm-256color ssh -p ${3:-22} $1@$2 -t "tmux new-session -s $1 || tmux attach-session -t $1"
}
Run Code Online (Sandbox Code Playgroud)

22默认使用端口.定义快速连接别名:

alias office-server='tmux-connect $USER 192.168.1.123'
alias cloud-server='tmux-connect root my.remote.vps.server.com 49281'
Run Code Online (Sandbox Code Playgroud)

无密码登录:

如果您不想每次都输入密码而不是生成.ssh密钥以自动登录:

ssh-keygen -t rsa
eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_rsa
Run Code Online (Sandbox Code Playgroud)

将您的公钥放到远程主机:

ssh-copy-id -p <port> user@hostname
Run Code Online (Sandbox Code Playgroud)

其他提示:

如果要使用与本地bash会话相对应的临时会话ID,请使用tmux id:

SID=$USER-$BASHPID
ssh user@host -t "tmux new-session -s $SID || tmux attach-session -t $SID"
Run Code Online (Sandbox Code Playgroud)

  • 在较新版本的tmux中,您还可以使用`tmux new-session -A`,如果它存在则将附加,否则它将创建一个新的. (4认同)

mon*_*too 14

我使用了来自@kingmeffisto的行(我不允许评论该答案)并且我添加了一个退出,因此终止tmux也会终止ssh连接.然而,这打破了SFTP会议,所以我不得不检查$SSH_TTY而不是$SSH_CONNECTION.

编辑4/2018:为交互式终端添加了测试,[[ $- =~ i ]]以允许像Ansible这样的工具工作.

if [ -z "$TMUX" ] && [ -n "$SSH_TTY" ] && [[ $- =~ i ]]; then
    tmux attach-session -t ssh || tmux new-session -s ssh
    exit
fi
Run Code Online (Sandbox Code Playgroud)


Fab*_*osa 11

本博文中所述,您可以使用单个命令ssh然后附加到现有的tmux会话:

ssh hostname -t tmux attach -t 0
Run Code Online (Sandbox Code Playgroud)

  • 这连接到一个名为"0"的会话.也就是说,一般形式是`ssh [hostname] -t tmux attach -t [sessionName]` (3认同)