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

时间:2008-11-20 11:44:26

标签: shell ssh sysadmin remote-execution

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

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

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

有没有办法使用plink / ssh运行?

20 个答案:

答案 0 :(得分:1101)

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

plink root@MachineB -m local_script.sh

如果机器A是基于Unix的系统,您可以使用:

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

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

答案 1 :(得分:561)

这是一个老问题,杰森的答案很好,但我想补充一点:

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,f​​tp等服务进行对话。但请记住,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

答案 2 :(得分:231)

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

这让我过去了。

例如:

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}'"

正确打印出“你好”。

答案 3 :(得分:143)

这是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'&lt;&lt;'ENDSSH'...

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

答案 4 :(得分:100)

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

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

答案 5 :(得分:26)

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

答案 6 :(得分:10)

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

答案 7 :(得分:9)

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

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

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

答案 8 :(得分:2)

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

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

答案 9 :(得分:2)

我用它来在远程机器上运行shell脚本(在/ bin / bash上测试):

ssh deploy@host . /home/deploy/path/to/script.sh

答案 10 :(得分:1)

chmod +x script.sh    
ssh -i key-file root@111.222.3.444 < ./script.sh

答案 11 :(得分:1)

cat ./script.sh | ssh <user>@<host>

答案 12 :(得分:1)

如果您想执行这样的命令 temp=`ls -a` echo $temp ``中的命令会导致错误。

下面的命令将解决此问题 ssh user@host ''' temp=`ls -a` echo $temp '''

答案 13 :(得分:1)

这里的答案(https://stackoverflow.com/a/2732991/4752883)效果很好 您正尝试使用plinkssh在远程Linux计算机上运行脚本。 如果脚本在linux上有多行,它将起作用。

**但是,如果您尝试运行位于本地的批处理脚本 linux/windows计算机和您的远程计算机是Windows,它包含在内 使用**

的多行

plink root@MachineB -m local_script.bat

不会工作。

只会执行脚本的第一行。这可能是一个 限制plink

解决方案1:

运行多行批处理脚本(特别是如果它相对简单, 由几行组成):

如果您的原始批处理脚本如下

cd C:\Users\ipython_user\Desktop 
python filename.py

你可以使用“&amp;&amp;”将这些线组合在一起分隔符如下所示 local_script.bat档案: https://stackoverflow.com/a/8055390/4752883

cd C:\Users\ipython_user\Desktop && python filename.py

在此更改之后,您可以按照此处的指示运行脚本 @ JasonR.Coombs:https://stackoverflow.com/a/2732991/4752883 with:

`plink root@MachineB -m local_script.bat`

解决方案2:

如果批处理脚本相对复杂,最好使用批处理 封装plink命令的脚本以及如下所述的脚本 在这里@Martin https://stackoverflow.com/a/32196999/4752883

rem Open tunnel in the background
start plink.exe -ssh [username]@[hostname] -L 3307:127.0.0.1:3306 -i "[SSH
key]" -N

rem Wait a second to let Plink establish the tunnel 
timeout /t 1

rem Run the task using the tunnel
"C:\Program Files\R\R-3.2.1\bin\x64\R.exe" CMD BATCH qidash.R

rem Kill the tunnel
taskkill /im plink.exe

答案 14 :(得分:1)

如果脚本很短并且打算嵌入到您的脚本中,并且您在 bash shell 下运行并且 bash shell 在远程端可用,您可以使用 {{1}将本地上下文传输到远程。定义包含将传输到远程的状态的变量和函数。定义一个将在远程端执行的函数。然后在 declare 读取的 here 文档中,您可以使用 bash -s 传输变量值并使用 declare -p 将函数定义传输到远程。

因为 declare -f 负责引用并将被远程 declare 解析,所以变量被正确引用并且函数被正确传输。您可能只是在本地编写脚本,通常我会在远程端完成一个很长的功能。必须精心挑选上下文,但以下方法对于任何短脚本来说都“足够好”并且是安全的 - 应该正确处理所有极端情况。

bash

答案 15 :(得分:0)

不清楚本地脚本是否使用本地设置的变量、函数或别名。

如果这样做应该可以:

myscript.sh:

#!/bin/bash

myalias $myvar
myfunction $myvar

它使用 $myvarmyfunctionmyalias。让我们假设它们是在本地设置的,而不是在远程机器上设置的。

制作一个包含脚本的 bash 函数:

eval "myfun() { `cat myscript.sh`; }"

设置变量、函数和别名:

myvar=works
alias myalias='echo This alias'
myfunction() { echo This function "$@"; }

并使用 GNU Parallel 的 myfunmyfunctionmyvarmyaliasserver 导出到 env_parallel

env_parallel -S server -N0  --nonall myfun ::: dummy

答案 16 :(得分:0)

这个bash脚本执行ssh到目标远程计算机,并在远程计算机上运行一些命令,不要忘记在运行之前安装expect(在mac brew install expect上)

#!/usr/bin/expect
set username "enterusenamehere"
set password "enterpasswordhere"
set hosts "enteripaddressofhosthere"
spawn ssh  $username@$hosts
expect "$username@$hosts's password:"
send -- "$password\n"
expect "$"
send -- "somecommand on target remote machine here\n"
sleep 5
expect "$"
send -- "exit\n"

答案 17 :(得分:0)

如果是一个脚本,那么使用上述解决方案就可以了。

我会设置 Ansible 来完成任务。它的工作方式相同(Ansible使用ssh在Unix或Windows的远程计算机上执行脚本。)

它将更加结构化和可维护。

答案 18 :(得分:0)

您可以使用runoverssh

sudo apt install runoverssh
runoverssh -s localscript.sh user host1 host2 host3...

-s远程运行​​本地脚本

有用的标志:
-g为所有主机使用全局密码(单个密码提示)
-n使用SSH代替sshpass,可用于公共密钥身份验证

答案 19 :(得分:-22)

首先,使用scp

将脚本复制到Machine B.
  

[user @ machineA] $ scp / path / to / script user @ machineB:/ home / user / path

然后,只需运行脚本

  

[user @ machineA] $ ssh user @ machineB“/ home / user / path / script”

如果您已为脚本提供了可执行权限,则此功能将起作用。