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

How to use SSH to run a shell script on a remote machine?

我必须在远程机器上运行shell脚本(windows/linux)。

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

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

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


如果machineA是一个windows框,您可以将plink(putty的一部分)与-m参数一起使用,它将在远程服务器上执行本地脚本。

1
plink root@MachineB -m local_script.sh

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

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

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


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

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

这也可以用于SU和需要用户输入的命令。(注意,'在这里越狱了)

编辑:由于这个答案一直得到一些流量,我会添加更多的信息到Heredoc的精彩使用中:

您可以用这种语法嵌套命令,这是嵌套工作的唯一方法(以一种明智的方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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,你可以用制表符缩进内部!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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


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

这在过去已经把我吸引住了。

例如:

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

打印输出/主页/用户2

虽然

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

打印输出/主页/用户

另一个例子:

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

正确打印"你好"。


这是Yarekt回答的扩展,将内联远程命令与将env变量从本地计算机传递到远程主机相结合,以便在远程端参数化脚本:

1
2
3
4
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之后发送所有内容。当远程机器执行命令arg1和arg2时,由于本地命令行评估(它定义了远程服务器上的环境变量),设置了本地值,然后使用这些变量执行bash-s命令。沃伊拉


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

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


我已经开始使用织物进行更复杂的操作。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上测试):

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

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

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


这里的答案(https://stackoverflow.com/a/2732991/4752883)如果您试图使用plinkssh在远程Linux机器上运行脚本。如果脚本在linux上有多行,它将工作。

**但是,如果您尝试运行位于本地linux/windows机,您的远程机是Windows机,由使用**

plink root@MachineB -m local_script.bat

不会工作。

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

解决方案1:

运行多行批处理脚本(特别是在相对简单的情况下,由几行组成):

如果原始批处理脚本如下

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

您可以使用"分隔符"将行组合在一起,如下所示local_script.bat文件:https://stackoverflow.com/a/8055390/4752883:

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

在这个更改之后,您就可以运行下面指出的脚本了@jasonr.coombs:https://stackoverflow.com/a/2732991/4752883,网址:

1
`plink root@MachineB -m local_script.bat`

解决方案2:

如果批处理脚本相对复杂,则最好使用批处理封装plink命令的脚本,如下所示以下作者:@martin https://stackoverflow.com/a/32196999/4752883:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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\
\
-3.2.1\\bin\\x64\
.exe" CMD BATCH qidash.R

rem Kill the tunnel
taskkill /im plink.exe


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/expect
set username"enterusenamehere"
set password"enterpasswordhere"
set hosts"enteripaddressofhosthere"
spawn ssh  $username@$hosts
expect"$username@$hosts's password:"
send --"$password\
"
expect"$"
send --"somecommand on target remote machine here\
"
sleep 5
expect"$"
send --"exit\
"


首先,使用scp将脚本复制到计算机b

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

然后,运行脚本

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

如果您已授予脚本可执行权限,则此操作将有效。