在 Bash 中 ssh 和运行多个命令的最干净的方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4412238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the cleanest way to ssh and run multiple commands in Bash?
提问by Eli
I already have an ssh agent set up, and I can run commands on an external server in Bash script doing stuff like:
我已经设置了一个 ssh 代理,我可以在 Bash 脚本中的外部服务器上运行命令,执行以下操作:
ssh blah_server "ls; pwd;"
Now, what I'd really like to do is run a lot of long commands on an external server. Enclosing all of these in between quotation marks would be quite ugly, and I'd really rather avoid ssh'ing multiple times just to avoid this.
现在,我真正想做的是在外部服务器上运行很多长命令。将所有这些括在引号之间会非常难看,我真的宁愿避免多次 ssh 来避免这种情况。
So, is there a way I can do this in one go enclosed in parentheses or something? I'm looking for something along the lines of:
那么,有没有一种方法可以一次性将其括在括号或其他内容中?我正在寻找以下方面的东西:
ssh blah_server (
ls some_folder;
./someaction.sh;
pwd;
)
Basically, I'll be happy with any solution as long as it's clean.
基本上,只要它是干净的,我就会对任何解决方案感到满意。
Edit
编辑
To clarify, I'm talking about this being part of a larger bash script. Other people might need to deal with the script down the line, so I'd like to keep it clean. I don't want to have a bash script with one line that looks like:
澄清一下,我说的是这是一个更大的 bash 脚本的一部分。其他人可能需要处理脚本,所以我想保持干净。我不想有一个 bash 脚本,其中一行看起来像:
ssh blah_server "ls some_folder; ./someaction.sh 'some params'; pwd; ./some_other_action 'other params';"
because it is extremely ugly and difficult to read.
因为它极其丑陋且难以阅读。
回答by Paul Tomblin
How about a Bash Here Document:
Bash Here 文档怎么样:
ssh otherhost << EOF
ls some_folder;
./someaction.sh 'some params'
pwd
./some_other_action 'other params'
EOF
To avoid the problems mentioned by @Globalz in the comments, you may be able to (depending what you're doing on the remote site) get away with replacing the first line with
为了避免@Globalz 在评论中提到的问题,您可以(取决于您在远程站点上执行的操作)将第一行替换为
ssh otherhost /bin/bash << EOF
Note that you can do variable substitution in the Here document, but you may have to deal with quoting issues. For instance, if you quote the "limit string" (ie. EOF
in the above), then you can't do variable substitutions. But without quoting the limit string, variables are substituted. For example, if you have defined $NAME
above in your shell script, you could do
请注意,您可以在 Here 文档中进行变量替换,但您可能需要处理引用问题。例如,如果您引用“限制字符串”(即EOF
在上面),则不能进行变量替换。但是没有引用限制字符串,变量被替换。例如,如果你$NAME
在你的 shell 脚本中定义了上面,你可以做
ssh otherhost /bin/bash << EOF
touch "/tmp/${NAME}"
EOF
and it would create a file on the destination otherhost
with the name of whatever you'd assigned to $NAME
. Other rules about shell script quoting also apply, but are too complicated to go into here.
它会在目标上创建一个文件,otherhost
名称为您分配给的任何内容$NAME
。其他有关 shell 脚本引用的规则也适用,但太复杂了,无法在这里介绍。
回答by bosmacs
Edit your script locally, then pipe it into ssh, e.g.
在本地编辑您的脚本,然后将其通过管道传输到 ssh,例如
cat commands-to-execute-remotely.sh | ssh blah_server
where commands-to-execute-remotely.sh
looks like your list above:
哪里commands-to-execute-remotely.sh
看起来像你上面的列表:
ls some_folder
./someaction.sh
pwd;
回答by Andrei B
To match your sample code, you can wrap your commands inside single or double qoutes. For example
为了匹配您的示例代码,您可以将您的命令包装在单引号或双引号中。例如
ssh blah_server "
ls
pwd
"
回答by terminus
I see two ways:
我看到两种方式:
First you make a control socket like this:
首先你制作一个像这样的控制插座:
ssh -oControlMaster=yes -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip>
and run your commands
并运行你的命令
ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip> -t <yourcommand>
This way you can write an ssh command without actually reconnecting to the server.
这样您就可以编写 ssh 命令而无需实际重新连接到服务器。
The second would be to dynamically generate the script, scp
ing it and running.
第二种是动态生成脚本,scp
运行它。
回答by R J
This can also be done as follows. Put your commands in a script, let's name it commands-inc.sh
这也可以如下完成。将您的命令放在脚本中,让我们将其命名为 commands-inc.sh
#!/bin/bash
ls some_folder
./someaction.sh
pwd
Save the file
保存文件
Now run it on the remote server.
现在在远程服务器上运行它。
ssh user@remote 'bash -s' < /path/to/commands-inc.sh
Never failed for me.
对我来说从来没有失败过。
回答by Jai Prakash
Put all the commands on to a script and it can be run like
将所有命令放在一个脚本中,它可以像这样运行
ssh <remote-user>@<remote-host> "bash -s" <./remote-commands.sh
回答by arnab
SSH and Run Multiple Commands in Bash.
SSH 和在 Bash 中运行多个命令。
Separate commands with semicolons within a string, passed to echo, all piped into the ssh command. For example:
在字符串中用分号分隔命令,传递给 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
回答by Aconcagua
For anyone stumbling over here like me - I had success with escaping the semicolon and the newline:
对于像我一样在这里磕磕绊绊的人 - 我成功地逃脱了分号和换行符:
First step: the semicolon. This way, we do not break the ssh command:
第一步:分号。这样,我们就不会破坏 ssh 命令:
ssh <host> echo test\;ls
^ backslash!
Listed the remote hosts /home directory (logged in as root), whereas
列出远程主机 /home 目录(以 root 身份登录),而
ssh <host> echo test;ls
^ NO backslash
listed the current working directory.
列出当前工作目录。
Next step: breaking up the line:
下一步:拆线:
v another backslash!
ssh <host> echo test\;\
ls
This again listed the remote working directory - improved formatting:
这再次列出了远程工作目录 - 改进了格式:
ssh <host>\
echo test\;\
ls
If really nicer than here document or quotes around broken lines - well, not me to decide...
如果真的比这里更好的文档或折线周围的引号 - 好吧,不是我来决定......
(Using bash, Ubuntu 14.04 LTS.)
(使用 bash,Ubuntu 14.04 LTS。)
回答by Michael Petrochuk
The posted answers using multiline strings and multiple bash scripts did not work for me.
使用多行字符串和多个 bash 脚本发布的答案对我不起作用。
- Long multiline strings are hard to maintain.
- Separate bash scripts do not maintain local variables.
- 长的多行字符串很难维护。
- 单独的 bash 脚本不维护局部变量。
Here is a functional way to ssh and run multiple commands while keeping local context.
这是一种在保持本地上下文的同时 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"
回答by DimiDak
Not sure if the cleanest for long commands but certainly the easiest:
不确定长命令是否最干净,但肯定是最简单的:
ssh user@host "cmd1; cmd2; cmd3"