我已经设置了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';"
因为它非常丑陋且难以阅读。
答案 0 :(得分:405)
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文档中执行变量替换,但您可能必须处理引用问题。例如,如果引用“限制字符串”(即上面的EOF
),那么就不能进行变量替换。但是,如果不引用限制字符串,则替换变量。例如,如果您在shell脚本中定义了上面的$NAME
,则可以执行
ssh otherhost /bin/bash << EOF
touch "/tmp/${NAME}"
EOF
它将在目标otherhost
上创建一个文件,其名称为您分配给$NAME
的内容。关于shell脚本引用的其他规则也适用,但过于复杂,无法进入此处。
答案 1 :(得分:108)
在本地编辑脚本,然后将其传送到ssh,例如
cat commands-to-execute-remotely.sh | ssh blah_server
commands-to-execute-remotely.sh
看起来像上面的列表:
ls some_folder
./someaction.sh
pwd;
答案 2 :(得分:33)
要匹配您的示例代码,您可以将命令包装在单个或双重qoutes中。例如
ssh blah_server "
ls
pwd
"
答案 3 :(得分:32)
我看到两种方式:
首先你制作一个这样的控制插座:
ssh -oControlMaster=yes -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip>
并运行您的命令
ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip> -t <yourcommand>
这样您就可以编写ssh命令而无需实际重新连接到服务器。
第二个是动态生成脚本,scp
并运行。
答案 4 :(得分:18)
这也可以如下完成。 将命令放在脚本中,命名为commands-inc.sh
#!/bin/bash
ls some_folder
./someaction.sh
pwd
保存文件
现在在远程服务器上运行它。
ssh user@remote 'bash -s' < /path/to/commands-inc.sh
对我来说永远不会失败。
答案 5 :(得分:8)
将所有命令放到脚本上,它可以像
一样运行ssh <remote-user>@<remote-host> "bash -s" <./remote-commands.sh
答案 6 :(得分:8)
在Bash中使用SSH和运行多个命令。
在字符串中用分号分隔命令,传递给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
答案 7 :(得分:6)
对于像我这样在这里磕磕绊绊的人 - 我成功逃脱了分号和换行符:
第一步:分号。这样,我们不会破坏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。)
答案 8 :(得分:4)
这适用于创建脚本,因为您不必包含其他文件:
#!/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
答案 9 :(得分:2)
配置系统默认情况下使用单个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。
答案 10 :(得分:2)
使用多行字符串和多个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"
答案 11 :(得分:1)
对于简单的命令,您可以使用:
ssh <ssh_args> command1 '&&' command2
或
ssh <ssh_args> command1 \&\& command2
答案 12 :(得分:0)
不确定长命令是否最干净,但肯定最简单:
ssh user@host "cmd1; cmd2; cmd;3"
答案 13 :(得分:0)
在 Bash 中 ssh 和运行多个命令的最干净的方法是什么?
使用这个 ssh 转义函数:
sshqfunc() { echo "bash -c $(printf "%q" "$(declare -f "$1"); $1 "\$@\"")"; };
函数以函数名作为参数,输出函数的declare -f
,然后用"$@"
参数调用它。然后函数被 "%q"
引用并添加 bash -c
。
定义一个你想在遥控器上完成的工作的函数。函数定义正常,所以它会是“干净的”:
work() {
ls
pwd
echo "Some other command"
}
您可以在本地测试此类功能。然后你可以:
ssh host@something "$(sshqfunc work)"
您也可以传递参数,它们将传递给您的函数。第一个参数是 $0
!
ssh host@something "$(sshqfunc work)" -- arg1 arg2