如何使用 SSH 在远程计算机上运行 Shell 脚本?

我必须在远程计算机上运行 Shell 脚本(Windows / Linux)。

我在机器 A 和 B 上都配置了 SSH。我的脚本在机器 A 上,它将在远程机器 B 上运行我的一些代码。

本地和远程计算机可以是 Windows 或 Unix 系统。

有没有办法使用 plink / ssh 来执行此操作?

答案

如果计算机 A 是 Windows 机器,则可以将 Plink( PuTTY 的一部分)与 - m 参数一起使用,它将在远程服务器上执行本地脚本。

plink root@MachineB -m local_script.sh

如果计算机 A 是基于 Unix 的系统,则可以使用:

ssh root@MachineB 'bash -s' < local_script.sh

您不必将脚本复制到远程服务器即可运行它。

这是一个古老的问题,Jason 的答案很好,但是我想补充一下:

ssh user@host <<'ENDSSH'
#commands to run on remote host
ENDSSH

这也可以与需要用户输入的 su 和命令一起使用。 (请注意'转义的 Heredoc)

编辑:由于此答案不断获得一些流量,我将添加更多信息到 heredoc 的这种出色用法:

您可以使用此语法嵌套命令,这就是嵌套似乎起作用的唯一方式(以合理的方式)

ssh user@host <<'ENDSSH'
#commands to run on remote host
ssh user@host2 <<'END2'
# Another bunch of commands on another host
wall <<'ENDWALL'
Error: Out of cheese
ENDWALL
ftp ftp.secureftp-test.com <<'ENDFTP'
test
test
ls
ENDFTP
END2
ENDSSH

您实际上可以与某些服务(例如 telnet,ftp 等)进行对话。但是请记住,heredoc 只是将 stdin 作为文本发送,它不等待行之间的响应

编辑:我刚刚发现,如果使用<<-END则可以缩进制表符的内部!

ssh user@host <<-'ENDSSH'
    #commands to run on remote host
    ssh user@host2 <<-'END2'
        # Another bunch of commands on another host
        wall <<-'ENDWALL'
            Error: Out of cheese
        ENDWALL
        ftp ftp.secureftp-test.com <<-'ENDFTP'
            test
            test
            ls
        ENDFTP
    END2
ENDSSH

(我认为这应该有效)

另请参阅http://tldp.org/LDP/abs/html/here-docs.html

另外,如果要从目标主机中提取变量,请不要忘记对变量进行转义。

过去,这让我感到困惑。

例如:

user@host> ssh user2@host2 "echo \$HOME"

打印出 / home / user2

user@host> ssh user2@host2 "echo $HOME"

打印出 / home / user

另一个例子:

user@host> ssh user2@host2 "echo hello world | awk '{print \$1}'"

正确打印出 “hello”。

这是 YarekT 回答的扩展,它结合了嵌入式远程命令和将 ENV 变量从本地计算机传递到远程主机的功能,因此您可以在远程端对脚本进行参数设置:

ssh user@host ARG1=$ARG1 ARG2=$ARG2 'bash -s' <<'ENDSSH'
  # commands to run on remote host
  echo $ARG1 $ARG2
ENDSSH

我发现将它们全部保存在一个脚本中非常有帮助,因此它非常易读和可维护。

为什么这样做。 ssh 支持以下语法:

ssh user @ host remote_command

在 bash 中,我们可以指定环境变量以在一行上运行命令之前定义,如下所示:

ENV_VAR_1 ='value1'ENV_VAR_2 ='value2'bash -c'echo $ ENV_VAR_1 $ ENV_VAR_2'

这使得在运行命令之前定义变量变得容易。在这种情况下,echo 是我们正在运行的命令。 echo 之前的所有内容都定义了环境变量。

因此,我们将这两个功能与 YarekT 的答案结合起来,得到:

ssh user @ host ARG1 = $ ARG1 ARG2 = $ ARG2'bash -s'<<'ENDSSH'...

在这种情况下,我们将 ARG1 和 ARG2 设置为本地值。在 user @ host 之后将所有内容作为 remote_command 发送。当远程计算机执行命令 ARG1 和 ARG2 时,设置了本地值,这要归功于本地命令行评估,该评估在远程服务器上定义了环境变量,然后使用这些变量执行 bash -s 命令。瞧

<hostA_shell_prompt>$ ssh user@hostB "ls -la"

这将提示您输入密码,除非您已将 hostA 用户的公共密钥复制到用户. ssh 目录的目录中的 authorized_keys 文件中。这将允许无密码身份验证(如果在 ssh 服务器的配置中被接受为 auth 方法)

我已经开始使用Fabric进行更复杂的操作。 Fabric 需要 Python 和其他几个依赖项,但仅在客户端计算机上。该服务器仅需要是 ssh 服务器。我发现此工具比传递给 SSH 的 Shell 脚本更强大,并且值得进行设置(特别是如果您喜欢使用 Python 编程)。 Fabric 处理多个主机(或具有某些角色的主机)上正在运行的脚本,帮助进行幂等操作(例如,将行添加到配置脚本中,但如果已经存在则不行),并允许构造更复杂的逻辑(例如 Python)语言可以提供)。

尝试运行ssh user@remote sh ./script.unx

假设您是想从 “本地” 计算机上自动执行此操作,而无需手动登录 “远程” 计算机,则应查看一个称为 Expect 的 TCL 扩展,它是专门为这种情况而设计的。我还提供了指向脚本的链接,该脚本用于通过 SSH 登录 / 交互。

https://www.nist.gov/services-resources/software/expect

http://bash.cyberciti.biz/security/expect-ssh-login-script/

我使用此脚本在远程计算机上运行 shell 脚本(在 / bin / bash 上测试):

ssh deploy@host . /home/deploy/path/to/script.sh
ssh user@hostname ".~/.bashrc;/cd path-to-file/;.filename.sh"

强烈建议您获取环境文件(.bashrc / .bashprofile / .profile)。在远程主机中运行某些命令之前,因为目标主机和源主机的环境变量可能会有所不同。