如何将多个ssh和scp命令编写到各种系统

时间:2012-05-14 23:10:37

标签: linux bash ssh scp

我想编写一系列涉及多个ssh和scp调用的命令。我每天都会手动执行此任务:

从LOCAL系统,ssh到SYSTEM1
SYSTEM1上的mkdir / tmp / data 从SYSTEM1,ssh到SYSTEM2
SYSTEM2上的mkdir / tmp / data 从SYSTEM2,SSH到SYSTEM3

来自SYSTEM3的scp文件:/ data到SYSTEM2:/ tmp / data
退出到SYSTEM2
来自SYSTEM2的scp文件:/ data和SYSTEM2:/ tmp / data到SYSTEM1:/ tmp / data
rm -fr SYSTEM2:/ tmp / data
退出到SYSTEM1
来自SYSTEM1的scp文件:/ data和SYSTEM1:/ tmp / data到LOCAL:/ data
rm -fr SYSTEM1:/ tmp / data

我每天至少进行一次此过程,不同系统之间大约需要5-10分钟,然后进行清理。我真的想在bash脚本中自动执行此操作,但到目前为止我的业余尝试都没有成功。正如您可能怀疑的那样,系统通信受到限制,这意味着LOCAL只能看到System1,System2只能看到System1和System3,system3只能看到system2等等。你明白了。做这个的最好方式是什么?此外,System1是许多其他系统的集线器,因此必须由用户指示SYSTEM2(与任何SYSTEM2相比,System3将始终具有相同的相对IP /主机名)。

我尝试在shell脚本中以正确的顺序放置命令,然后在提示时手动输入密码(这已经是效率的巨大提高)但是方法不起作用或我的执行脚本错了。另外,我希望为脚本创建一个命令行参数,该参数将采用“system2”连接的模式,要复制的数据模式以及本地系统上数据的目标位置。

./grab_data system2 *05-14* ~/grabbed-data

我做了一些搜索,我认为我的下一步是在每个执行本地任务的系统上安装脚本,然后通过相应远程系统的ssh命令执行脚本。有没有更好的办法?我应该使用哪些命令以及这种自动化这种嵌套ssh和scp问题的一般方法是什么?

我意识到我的描述可能有点令人费解,所以请询问我没有正确描述的任何领域的澄清。

感谢。

3 个答案:

答案 0 :(得分:3)

通过在其他ssh连接上隧道连接ssh连接,可以大大简化此过程(请参阅this previous answer)。我这样做的方法是在LOCAL系统上创建一个.ssh / config文件,其中包含以下条目:

Host SYSTEM3
        ProxyCommand    ssh -e none SYSTEM2 exec /usr/bin/nc %h %p 2>/dev/null
        HostName        SYSTEM3.full.domain
        User            system3user

Host SYSTEM2
        ProxyCommand    ssh -e none SYSTEM1 exec /usr/bin/nc %h %p 2>/dev/null
        HostName        SYSTEM2.full.domain
        User            system2user

Host SYSTEM1
        HostName        SYSTEM1.full.domain
        User            system1user

(假设两个中间主机都将netcat安装为/ usr / bin / nc - 如果没有,您可能必须找到/安装一些将stdin& stdout网关到TCP会话中的等效方法。)

通过这个设置,你可以在LOCAL上使用scp SYSTEM3:/data /data,它将自动隧道通过SYSTEM1和SYSTEM2(并按顺序询问三个SYSTEMn的密码 - 这可能有点令人困惑,特别是如果你错误输入一个)。

答案 1 :(得分:0)

如果要连接到多个系统,特别是如果必须通过中间主机转发连接,则需要使用启用了ssh-agent转发的公钥身份验证。这样,您只需要进行一次身份验证。

如果您需要做的就是从远程命令检查退出状态,那么带代理转发的脚本SSH可能就足够了,但如果您要做任何复杂的事情,最好使用expect或expect-lite来驱动SSH / SCP会话以更灵活的方式进行。特别是Expect旨在成为交互式会话的强大替代品。

如果您坚持使用shell脚本,并且您的文件名发生了很大的变化,您可以随时创建一个围绕SSH或SCP的包装器:

# usage: my_ssh [remote_host] [command_line]
# returns: exit status of remote command, or 255 on SSH error
my_ssh () {
    local host="$1"
    shift
    ssh -A "$host" "$@"
}

在ssh-agent和包装函数之间,你应该为自己的努力找到一个合理的起点。

答案 2 :(得分:0)

另一种方法是使用rsync,它可以创建任何所需的目录,如果需要,还可以删除复制的源文件。

在您的情况下,您可以使用命令

home:~$ ssh system1
system1:~$ ssh system2
system2:~$ rsync -aPSHiv system3:/data /tmp/data
system2:~$ exit
system1:~$ rsync -aPSHiv --remove-source-files system2:/tmp/data /tmp/data
system1:~$ rsync -aPSHiv system2:/data /tmp/data
system1:~$ exit
home:~$ rsync -aPSHiv --remove-source-files system1:/tmp/data /tmp/data
home:~$ rsync -aPSHiv system1:/data /data

如果将其与Gordon's approach结合使用,您甚至可以将其缩小为

home:~$ rsync -aPSHiv system1:/data/ system2:/data/ system3:/data/ /data/

请注意rsync...data...data/之间有所区别 - 前者表示目录及其内容,后者只是内容。如果将它们混合起来,最终可能会在另一个目录data中找到目录data

此外,如果使用公共SSH密钥而不是密码,则可以简化操作。