首页 文章

什么是在Bash中ssh和运行多个命令最干净的方法?

提问于
浏览
258

我已经设置了ssh代理,我可以在Bash脚本中运行外部服务器上的命令,例如:

ssh blah_server "ls; pwd;"

现在,我真正想做的是在外部服务器上运行很多长命令 . 将所有这些包含在引号之间会非常难看,而且我宁愿多次避免ssh'ing以避免这种情况 .

那么,有没有办法可以用括号括起来的方式一次性地做到这一点?我正在寻找以下内容:

ssh blah_server (
   ls some_folder;
   ./someaction.sh;
   pwd;
)

基本上,只要它干净,我会对任何解决方案感到满意 .

编辑

为了澄清,我说的是这是一个更大的bash脚本的一部分 . 其他人可能需要处理脚本,所以我想保持清洁 . 我不希望有一个bash脚本,其中一行看起来像:

ssh blah_server "ls some_folder; ./someaction.sh 'some params'; pwd; ./some_other_action 'other params';"

因为它非常丑陋且难以阅读 .

12 回答

  • 5

    Bash怎么样Here Document

    ssh otherhost << EOF
      ls some_folder; 
      ./someaction.sh 'some params'
      pwd
      ./some_other_action 'other params'
    EOF
    

    为了避免评论中@Globalz提到的问题,您可能(取决于您在远程站点上所做的事情)躲开更换第一行

    ssh otherhost /bin/bash << EOF
    

    请注意,您可以在Here文档中执行变量替换,但您可能必须处理引用问题 . 例如,如果引用"limit string"(即上面的 EOF ),那么就不能进行变量替换 . 但是,如果不引用限制字符串,则替换变量 . 例如,如果您在shell脚本中定义了 $NAME ,则可以这样做

    ssh otherhost /bin/bash << EOF
    touch "/tmp/${NAME}"
    EOF
    

    它将在目标 otherhost 上创建一个文件,其名称为您分配给 $NAME 的任何名称 . 关于shell脚本引用的其他规则也适用,但过于复杂,无法进入此处 .

  • 16

    在本地编辑脚本,然后将其传输到ssh,例如

    cat commands-to-execute-remotely.sh | ssh blah_server
    

    其中 commands-to-execute-remotely.sh 看起来像上面的列表:

    ls some_folder
    ./someaction.sh
    pwd;
    
  • 99

    要匹配您的示例代码,您可以将命令包装在单个或双重qoutes中 . 例如

    ssh blah_server "
      ls
      pwd
    "
    
  • 2

    我看到两种方式:

    首先你制作一个这样的控制插座:

    ssh -oControlMaster=yes -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip>
    

    并运行您的命令

    ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip> -t <yourcommand>
    

    这样您就可以编写ssh命令而无需实际重新连接到服务器 .

    第二个是动态生成脚本,然后运行它 .

  • 32

    这也可以如下完成 . 将命令放在脚本中,我们将其命名为commands-inc.sh

    #!/bin/bash
    ls some_folder
    ./someaction.sh
    pwd
    

    保存文件

    现在在远程服务器上运行它 .

    ssh user@remote 'bash -s' < /path/to/commands-inc.sh
    

    从未对我失败过 .

  • 7

    SSH and Run Multiple Commands in Bash.

    用字符串中的分号分隔命令,传递给echo,所有命令都通过管道输入ssh命令 . 例如:

    echo "df -k;uname -a" | ssh 192.168.79.134
    
    Pseudo-terminal will not be allocated because stdin is not a terminal.
    Filesystem     1K-blocks    Used Available Use% Mounted on
    /dev/sda2       18274628 2546476  14799848  15% /
    tmpfs             183620      72    183548   1% /dev/shm
    /dev/sda1         297485   39074    243051  14% /boot
    Linux newserv 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux
    
  • 367

    将所有命令放在脚本上,它可以像运行一样运行

    ssh <remote-user>@<remote-host> "bash -s" <./remote-commands.sh
    
  • 8

    对于像我这样在这里磕磕绊绊的人 - 我成功逃脱了分号和换行符:

    第一步:分号 . 这样,我们不会破坏ssh命令:

    ssh <host> echo test\;ls
                        ^ backslash!
    

    列出远程主机/主目录(以root身份登录),而

    ssh <host> echo test;ls
                        ^ NO backslash
    

    列出了当前的工作目录 .

    下一步:分手:

    v another backslash!
    ssh <host> echo test\;\
    ls
    

    这再次列出了远程工作目录 - 改进了格式:

    ssh <host>\
      echo test\;\
      ls
    

    如果真的比这里更好的文件或引用虚线 - 好吧,不是我决定...

    (使用bash,Ubuntu 14.04 LTS . )

  • 2

    这适用于创建脚本,因为您不必包含其他文件:

    #!/bin/bash
    ssh <my_user>@<my_host> "bash -s" << EOF
        # here you just type all your commmands, as you can see, i.e.
        touch /tmp/test1;
        touch /tmp/test2;
        touch /tmp/test3;
    EOF
    
  • 4

    最简单的方法是将系统配置为默认情况下使用单个ssh会话进行多路复用 .

    这可以通过为套接字创建一个文件夹来完成:

    mkdir ~/.ssh/controlmasters
    

    然后将以下内容添加到.ssh配置中:

    Host *
        ControlMaster auto
        ControlPath ~/.ssh/controlmasters/%r@%h:%p.socket
        ControlMaster auto
        ControlPersist 10m
    

    现在,您无需修改任何代码 . 这允许多次调用ssh和scp而无需创建多个会话,这在本地和远程计算机之间需要更多交互时非常有用 .

    感谢@ terminus的回答,http://www.cyberciti.biz/faq/linux-unix-osx-bsd-ssh-multiplexing-to-speed-up-ssh-connections/https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing .

  • 0

    使用多行字符串和多个bash脚本发布的答案对我不起作用 .

    • 长多行字符串很难维护 .

    • 单独的bash脚本不维护局部变量 .

    这是一种在保持本地上下文的同时ssh和运行多个命令的功能方法 .

    LOCAL_VARIABLE=test
    
    run_remote() {
        echo "$LOCAL_VARIABLE"
        ls some_folder; 
        ./someaction.sh 'some params'
        ./some_other_action 'other params'
    }
    
    ssh otherhost "$(set); run_remote"
    
  • 31

    不确定对于长命令是否最干净,但肯定是最简单的:

    ssh user@host "cmd1; cmd2; cmd;3"
    

相关问题