【问题标题】:How to script multiple ssh and scp commands to various systems如何为各种系统编写多个 ssh 和 scp 命令脚本
【发布时间】:2012-05-22 11:04:49
【问题描述】:

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

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

scp 文件从 SYSTEM3:/data 到 SYSTEM2:/tmp/data
退出到 SYSTEM2
scp 文件从 SYSTEM2:/data 和 SYSTEM2:/tmp/data 到 SYSTEM1:/tmp/data
rm -fr SYSTEM2:/tmp/数据
退出 SYSTEM1
scp 文件从 SYSTEM1:/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 问题的一般方法是什么?

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

谢谢。

【问题讨论】:

标签: linux bash ssh scp


【解决方案1】:

您可以通过在其他 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 的密码 - 这可能有点令人困惑,尤其是如果你打错了一个)。

【讨论】:

  • 这似乎是迄今为止最好的建议。我试了一下,我可以进入“System2”,但不幸的是,由于密钥/对锁定,我无法进入“System3”。这是系统管理员在我们这边实施的。您只能使用特定用户名从 System2 SSH 到 System3,显然,当我使用上述方法时,它会拒绝来自本地系统的密钥/对。有没有办法让代理连接在连接到 System3 时使用来自 System2 的 ssh 密钥,而不是使用我的本地密钥?
  • 如果我理解限制正确,您需要做的就是将 id 文件(类似于 ~/.ssh/id_rsa 或 id_dsa)从 SYSTEM2 复制到 LOCAL 下,使用备用名称(如 ~/. ssh/SYSTEM3_id_rsa),然后将IdentityFile ~/.ssh/SYSTEM3_id_rsa添加到本地配置文件的SYSTEM3部分。
  • 完美运行。谢谢先生。
【解决方案2】:

如果您要连接到多个系统,尤其是如果您必须通过中间主机转发连接,您将需要使用启用了 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 和 wrapper 函数之间,你应该有一个合理的起点来进行自己的努力。

【讨论】:

    【解决方案3】:

    另一种方法是使用 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 密钥而不是密码,则可以简化事情。

    【讨论】:

      猜你喜欢
      • 2018-06-07
      • 1970-01-01
      • 2015-11-11
      • 1970-01-01
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多