在许多服务器上通过SSH自动运行命令


46

.txt文件中有一个IP地址列表,例如:

1.1.1.1
2.2.2.2
3.3.3.3

每个IP地址的后面都有一个服务器,并且每个服务器上的端口22上都运行着一个sshd。known_hosts列表中并不是每个服务器(在我的PC上为Ubuntu 10.04 LTS / bash)。

如何在这些服务器上运行命令并收集输出?

理想情况下,我想在所有服务器上并行运行命令。

我将在所有服务器上使用公钥身份验证。

以下是一些潜在的陷阱:

  • ssh提示我将给定服务器的ssh密钥放入我的known_hosts文件中。
  • 给定的命令可能返回非零退出代码,指示输出可能无效。我需要认识到这一点。
  • 例如,由于网络错误,可能无法建立到给定服务器的连接。
  • 如果命令的运行时间比预期的长,或者服务器在运行命令时关闭,则应该有一个超时时间。

服务器是AIX / ksh(但我认为那并不重要。



1
我认为这不是重复的,因为您提到的链接甚至都不包含SSH。
LanceBaynes

4
如果尚未这样做,则应在所有计算机上设置ssh服务器,在工作计算机上建立私钥/公钥对,并将公钥复制到服务器上的帐户,以防止进一步的密码麻烦。这适用于我的答案,也适用于@demure。
安东

Answers:


14

假设您无法安装pssh或其他产品,则可以执行以下操作:

tmpdir=${TMPDIR:-/tmp}/pssh.$$
mkdir -p $tmpdir
count=0
while IFS= read -r userhost; do
    ssh -n -o BatchMode=yes ${userhost} 'uname -a' > ${tmpdir}/${userhost} 2>&1 &
    count=`expr $count + 1`
done < userhost.lst
while [ $count -gt 0 ]; do
    wait $pids
    count=`expr $count - 1`
done
echo "Output for hosts are in $tmpdir"

1
在此脚本中确切等待什么?ty!
LanceBaynes

如果服务器密钥不在我的knows_hosts文件中,该怎么办?
LanceBaynes

5
将脚本置于后台会创建子进程。当子进程退出时,进程“插槽”和资源将保留在系统中,直到父进程退出或父进程“等待”子进程为止。这些“仍然存在”终止的过程称为“僵尸”过程。在孩子进行诉讼并回收资源后进行清理是个好习惯。
Arcege”

1
如果不知道,那可能会搞砸它,但是您可以添加-o StrictHostKeyChecking=no以避免这种情况。但是,最好先从命令行扫描所有服务器,以便可以添加主机密钥。
2011年

1
如前所述,在将ssh程序置于后台并退出后,仍然保留资源。该wait命令回收那些资源,包括进程的返回码(进程如何退出)。然后,如果在程序的后面,您在后台放置了另一个进程,比如说一个压缩,需要等待它,那么如果没有该循环,则等待将回收一个完整的ssh程序,而不是压缩程序-可能仍然正在运行。您将在错误的子进程中获得返回状态。最好自己清理一下。
Arcege 2011年

61

有几种工具可以让您同时登录多台计算机并在其中执行一系列命令。这是一对:


1
您可能想要将pdsh添加到列表中。
里卡多·穆里

1
我发现clusterssh使用起来相当直观。只是我的2美分...
josinalvo

1
我经常使用pssh。它工作得很好,尽管我希望我能告诉我某些远程命令将具有非零的退出代码,但这并不意味着错误。那纯粹是化妆品。
安东尼·克拉克

1
@AnthonyClark您可以在这些命令后附加“ || true”之类的内容。
exic

16

如果您不仅喜欢使用Python脚本编写 bash脚本,那么Fabric可能是适合您的工具。

Fabric主页

Fabric是一个Python(2.5或更高版本)库和命令行工具,用于简化SSH在应用程序部署或系统管理任务中的使用。

它提供了用于执行本地或远程Shell命令(通常或通过sudo)和上载/下载文件的基本操作套件,以及诸如提示正在运行的用户进行输入或中止执行等辅助功能。

典型的用途包括创建一个包含一个或多个函数的Python模块,然后通过fab命令行工具执行它们。


Fabric v1很棒。不幸的是,Fabric v2删除了使其在此用例中有用的大多数功能-目前不推荐使用(2018年6月)。
Meekohi

11

我确实使用GNU并行,最具体地说,您可以使用以下配方:

parallel --tag --nonall --slf your.txt command

带有your.txt服务器IP地址/名称的文件。


是不是有只使用ssh因为我用我公司的服务器,我不想安装额外的软件包任何其他方式
Özzesh

当然,我以前也曾经这样做过ssh,但是您需要某种方式登录到其他计算机,并且这些方式以前不太安全(例如rsh)。您无需描述您正在使用的从一台机器到另一台机器的内容(telnet?,rsh?)。
Anthon

1
@Özzesh是的,仅适用于控制器
Anthon


1
@OleTange刚意识到谁在评论我的答案%-)。感谢这款出色的软件。
Anthon

8

基本设置:

for host in $(cat hosts.txt); do ssh "$host" "$command" >"output.$host"; done

使用名称/密码进行身份验证确实不是一个好主意。您应该为此设置一个私钥:

ssh-keygen && for host in $(cat hosts.txt); do ssh-copy-id $host; done

1
这是我一直在寻找的那个!由于michas
Özzesh

上面的脚本对我来说效果很好,但是在10台服务器中执行后,脚本没有响应。如何注销我连接的ssh服务器?
Özzesh

您无需显式注销。该“脚本”将仅在ssh $host $command每个主机上运行。尝试手动运行这些命令以了解发生了什么。
2013年


2

我认为您正在寻找pssh和通常的scp,rsync等的相关并行版本。


距离删除一票之遥,但是稍后的答案是+10。完全有道理
迈克尔·莫罗泽克

@MichaelMrozek比你知道的还要糟糕。这两个VTD中的第二个是我在发生点击高兴事件时发生的。我已将此标签打开了几天,打算标记或ping您将其删除的VTD还原。也许您现在可以将其翻转以清除选票。
Caleb 2014年

@Caleb解决了它
Michael Mrozek

2

我构建了一个名为Overcast的开源工具,以简化此类操作。

首先,定义服务器:

overcast import vm.01 --ip 1.1.1.1 --ssh-key /path/to/key
overcast import vm.02 --ip 2.2.2.2 --ssh-key /path/to/key

然后,您可以依次或并行运行多个命令和脚本文件,如下所示:

overcast run vm.* uptime "free -m" /path/to/script --parallel

2

Hypertable的项目最近增加了多主机的ssh工具。该工具使用libssh构建,可建立连接并异步并行发出命令,实现最大的并行度。有关完整的文档,请参阅多主机SSH工具。要在一组主机上运行命令,请按以下方式运行它:

$ ht ssh 1.1.1.1,2.2.2.2,3.3.3.3 uptime

您还可以指定主机名或IP模式,例如:

$ ht ssh 1.1.1.[1-99] uptime
$ ht ssh host[00-99] uptime

它还支持一个--random-start-delay <millis>选项,该选项会将每个主机上的命令启动延迟0到<millis>毫秒之间的随机时间间隔。当运行的命令访问中央资源时,可以使用此选项来避免出现雷电群问题。


2

我已经开发了collectnode非常简单有效的方法来使任务在多个服务器上执行(包括Windows)

如何使用CollectNode:

  1. 创建服务器列表,以使用:

    # cat hosts.file
    server1
    server2
    server3
    server4
    server5
    
  2. 执行CollectNode传递服务列表:

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User'
    
  3. 最佳地,可以过滤结果,例如,此命令仅显示满足条件的服务器。

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User' --where="command contain User"
    

https://collectnode.com/5-tasks-collectnode-can-help-managing-servers/


1
看来您是CollectNode的开发人员。在这种情况下,您应该在答案中披露,否则这只是垃圾邮件。
muru 18-3-2,1

抱歉,这不是我的意图,将答案修改为更具体。
fvidalmolina

1

一个非常好的问题的提示:

我发现的最好的解决方案是tmux,这并不奇怪。

您可以执行Ctrl-B:setw在tmux中进行同步窗格以实现惊人的结果。为此,您必须在Tmux的1个窗口的不同窗格中打开所有ssh连接。


0

也许这样的事情可以在多个主机上运行命令吗?假设所有主机都在.ssh / config中设置为无密码登录。

$ < hosts.txt xargs -I {} ssh {} command



0

使用Paramiko http://www.paramiko.org/和基于线程的并行性https://docs.python.org/3/library/threading.html。以下代码允许在每个服务器上并行执行多个命令!

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.load_system_host_keys()
ssh.connect(hostname, port, username, password)
t = threading.Thread(target=tasks[index], args=(ssh, box_ip,))
t.start()

注意:对每台服务器重复以上说明。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.