什么是最简洁的方式来在Bash中运行多个命令?

我已经设置了一个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';" 

因为这是非常难看和难以阅读。

如何在这里打一个文件 :

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

为了避免@Globalz在评论中提到的问题,你可以(取决于你在远程站点上做什么),用第一行代替

 ssh otherhost /bin/bash << EOF 

请注意,您可以在Here文档中进行variablesreplace,但是您可能需要处理引用问题。 例如,如果引用“限制string”(即上面的EOF ),则不能进行variablesreplace。 但是没有引用限制string,variables被replace。 例如,如果您在shell脚本中定义$NAME上面的$NAME ,则可以这样做

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

它会在目标otherhost上创build一个文件,其名称是你分配给$NAME 。 关于shell脚本引用的其他规则也适用,但是这里太复杂了。

在本地编辑你的脚本,然后将其pipe理到ssh中,例如

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

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

 ls some_folder ./someaction.sh pwd; 

我看到两种方式:

首先你做一个这样的控制套接字:

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

并运行你的命令

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

这样你就可以编写一个ssh命令,而不需要重新连接服务器。

第二个是dynamic生成脚本, scp并运行。

为了匹配您的示例代码,您可以将您的命令封装在单个或双个qoutes中。 例如

 ssh blah_server " ls pwd " 

这也可以如下完成。 把你的命令放在一个脚本中,让我们命名为commands-inc.sh

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

保存文件

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

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

从来没有失败过。

SSH和在Bash中运行多个命令。

在string中用分号分隔命令,传递给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 

把所有的命令放在一个脚本上,它可以运行

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

一个想法:

将你的长命令包装在一个bash脚本中, scp到目标服务器,用ssh执行,并在脚本结尾处有一个“delete-self”命令。

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

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

最简单的方法来configuration您的系统默认使用单个ssh会话多路复用。

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

 mkdir ~/.ssh/controlmasters 

然后将以下内容添加到.sshconfiguration中:

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

现在,你不需要修改你的任何代码。 这允许多次调用ssh和scp而不创build多个会话,当需要在本地和远程机器之间进行更多的交互时这非常有用。

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

对于像我这样在这里磕磕绊绊的人 – 我已经成功地转义了分号和换行符:

第一步:分号。 这样,我们不会中断ssh命令:

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

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

 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。)

使用多行string和多个bash脚本发布的答案不适合我。

  • 长的多行string很难维护。
  • 单独的bash脚本不保留局部variables。

这是一个function方式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"