我已经有一个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';"
因为它极其丑陋,难以阅读。
在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")"
如何使用Bash Here文档:
ssh otherhost << EOF
ls some_folder;
./someaction.sh 'some params'
pwd
./some_other_action 'other params'
EOF
为了避免@Globalz在评论中提到的问题,您可以(取决于您在远程站点上做什么)将第一行替换为
ssh otherhost /bin/bash << EOF
注意,您可以在Here文档中进行变量替换,但可能必须处理引用问题。例如,如果您引用“限制字符串”(即。EOF),那么你就不能做变量替换。但是不引用极限字符串,变量被替换了。例如,如果您在shell脚本中定义了上面的$NAME,您可以这样做
ssh otherhost /bin/bash << EOF
touch "/tmp/${NAME}"
EOF
它会在目标主机上创建一个文件,文件的名称与你分配给$ name的名称相同。关于shell脚本引用的其他规则也适用,但太复杂了,这里不详细介绍。