Shell Tips: 用GNU Screen实现发送交互到所有会话

服务器冗余和分拆是互联网服务中经常用来缓解访问压力的手段,那么检查或者管理多台同构服务器也是互联网行业工程师们绕不开的操作。经常面临的问题是:如何高效地在多台服务器上执行相同的命令,进行批量系统操作或问题检查。

Windows 下的 ssh 客户端 XShellSecureCRT 都提供了类似的功能,当每个标签页都连接到一个服务器时,可以在命令窗口中发送交互到所有的标签页以实现同时操作多台服务器的目的。这招我还是从 OP 那里学来的,的确大大提高了生产力。

但这种方法也存在一些问题:

  1. 只适用于特定的 ssh 客户端。例如对 Linux 来说就有些不适用,不过据说 Konsole 也提供了类似功能,未验证。
  2. 每个标签页中,还是得一台一台地登陆上服务器,很难自动化。据说有的客户端支持编写脚本实现,但还要学习对应脚本语言,且灵活性有限。
  3. 无法一直保持持续的连接。特别是对有开发机的工程师,本来开发机是一直在线的,但由于客户端的限制,只能在本地电脑连接多服务器。当本地网络断开后,自然多服务器的连接也断开了。

为了解决这些问题,小弟想到了神器 GNU Screen。Screen 也是终端,难道无法做这件事吗?您还别说,在我费心劳力一上午之后,总算摸索出了用 Screen 解决上述问题的方法。下面两个可以放到 ~/.bashrc 中的函数,就是我心血的“结晶” :)

function screenssh ()
{
    local username=YOUR_USERNAME
    local password=YOUR_PASSWORD
    local server=''
    local timeout=3
    for server in $@; do
        screen -S $STY -X screen ssh $username@$server
    done
    sleep $timeout
    local cmd="screen -S $STY -X at ssh# stuff $'$password\n'"
    eval $cmd
}

function lets ()
{
    local cmd="screen -S $STY -X at ssh# stuff $'$1\n'"
    eval $cmd
}

Screen 的用法和技巧,在我之前的文章中也有提及,此处不再赘述。这里主要介绍一下上面两个函数的作用和用法:

screenssh 是在 screen 中自动登陆多台服务器的命令。这个 bash 函数接受服务器列表作为输入,执行后会在当前 screen 中为每个服务器打开一个 window,并使用提供的用户名和密码登陆这些服务器。这样当前 screen 中就会多出 N 个 window,分别对应登陆到 N 个服务器。在使用前,你要修改用户名、密码变量值为你需要的内容,而且该命令必须在 screen 中执行,在 screen 外执行是无效的。

执行完 screenssh 后,就可以祭出 lets 命令来在多个 window 中同时执行操作命令了。lets 接受一个字符串作为输入,执行后该字符串会作为命令发送到 N 个服务器对应的 N 个 windows 中执行。

看完以后令人困惑的地方可能是,我到底应该在哪里执行 screenssh 和 lets 这两个命令呢?下面用一个例子来更直白地阐述一下这两个命令的使用方法。

假设你需要在 3 台服务器:s1.solrex.org, s2.solrex.org, s3.solrex.org 上执行 grep FATAL ~/error_log 查看错误日志。那么你应当:

1. $ screen -S admin
# 首先创建一个 screen,这时候你有了 0 号 window;
2. $ screenssh s1.solrex.org s2.solrex.org s3.solrex.org
# 在 0 号 window 中执行 screenssh 命令,自动打开 3 个 window,连接到三个不同的服务器;
3. $ lets "grep FATAL ~/error_log"
# 在 0 号 window 中执行 lets,将命令自动分发到 3 台服务器上执行;
4. ctrl-a N 切换到不同的 window 查看命令的执行情况;
5. ctrl-a 0 切换到 0 号 window 执行下一条批量命令;

下面我们再回顾一下上文中提到的 3 个问题是否解决了:1. GNU Screen Linux 一般均自带,不存在专用客户端问题;2. screenssh 解决了自动化登陆多台服务器问题,且服务器列表作为参数,非常灵活且易定制;3. 开发机上运行的 screen 保证了客户端离线连接不断。

《Shell Tips: 用GNU Screen实现发送交互到所有会话》上有9条评论

  1. 如果 多台服务器 的密码 不一样的话, 好像不太好办.....

    solrex, 有什么好的方法吗?

    1. @khb_gl 这可是 shell 脚本呀,你完全可以自定义的。比如把服务器、用户名、密码记录放在一个文件中,读入进来。

回复 Willings 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注