我已经有一个ssh代理设置,我可以在外部服务器上运行命令在Bash脚本做这样的事情:

ssh blah_server "ls; pwd;"

现在,我真正想做的是在外部服务器上运行大量长命令。把所有这些都放在引号之间会很难看,为了避免这种情况,我真的宁愿避免多次ssh。

有没有一种方法可以一次性完成,用括号括起来?我想要的是:

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

基本上,我对任何解决方案都很满意只要它是干净的。

Edit

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

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

因为它极其丑陋,难以阅读。


当前回答

SSH和在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

其他回答

使用多行字符串和多个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"

SSH和在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

为了匹配示例代码,可以将命令包装在单引号或双引号中。例如

ssh blah_server "
  ls
  pwd
"

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

我推荐使用这个转义函数。该函数接受一个参数——转义函数。然后sshqfunc输出函数的declare -f,然后输出一个字符串,该字符串将调用函数,并正确地引用“$@”参数。然后将整个代码加引号“%q”,并添加bash -c。如果远程没有bash,您可以将bash更改为sh。

sshqfunc() { echo "bash -c $(printf "%q" "$(declare -f "$@"); $1 \"\$@\"")"; };

然后定义一个函数,其中包含您想在远程上执行的工作。函数的定义是正常的,因此它将是适当的“干净”。您可以在本地测试这样的函数。定义之后,将正确转义的函数传递给远程。

work() {
   ls
   pwd
   echo "Some other command"
}

ssh host@something "$(sshqfunc work)"

你也可以传递参数,它们将作为位置参数传递给你的函数。函数后的下一个参数将被赋值为$0——通常是类似于——或_的占位符,用于将参数与调用分开。

work() {
   file=$1
   num=$2
   ls "$file"
   echo "num is $num"
}

ssh host@something "$(sshqfunc work)" -- /this/file 5

但请注意,如果有任何神奇的字符,参数也应该被正确引用:

ssh host@something "$(sshqfunc work)" -- "$(printf "%q" "$var1" "$var2")"

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

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