You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

脚本中为何要将SSH远程执行命令用双引号包裹?

关于SSH脚本中双引号的疑问解答

先看你提到的示例脚本:

#!/usr/bin/bash
#
USR='student'
OUT='/home/student/output'
#
for SRV in servera serverb
  do
ssh ${USR}@${SRV} "hostname -f" > ${OUT}-${SRV}
echo "#####" >> ${OUT}-${SRV}
ssh ${USR}@${SRV} "lscpu | grep '^CPU'" >> ${OUT}-${SRV}
echo "#####" >> ${OUT}-${SRV}
ssh ${USR}@${SRV} "grep -v '^$' /etc/selinux/config|grep -v '^#'" >> ${OUT}-${SRV}
echo "#####" >> ${OUT}-${SRV}
ssh ${USR}@${SRV} "sudo grep 'Failed password' /var/log/secure" >> ${OUT}-${SRV}
echo "#####" >> ${OUT}-${SRV}
done

针对你的三个问题,解答如下:

1. 这些双引号的作用是什么?

双引号核心是把远程要执行的命令打包成完整参数传给ssh,同时处理本地与远程shell的解析边界:

  • 防止本地shell拆分命令里的特殊字符(比如管道|、空格),确保整个命令作为一个整体发送给远程主机;
  • 保留内部的单引号,让远程shell能正确识别正则表达式(比如'^CPU'),不会被本地shell提前解析;
  • 如果远程命令需要用到本地变量,双引号还能让本地shell先完成变量替换再传给远程,这个示例里没用到这种场景,但也是双引号的实用特性。

2. 为何只包裹每行的一部分内容?

这里被包裹的是要传给远程执行的命令段,前面的${USR}@${SRV}是本地要解析的主机地址参数,不能和命令段一起包裹:

  • 如果把${USR}@${SRV} "hostname -f"整个用引号包起来,ssh会把这个完整字符串当成一个主机名解析,根本无法连接到正确的服务器;
  • 拆分包裹是为了明确区分“本地处理的参数”和“远程执行的命令”,前者由本地shell完成变量展开,后者作为完整单元传递给远程执行。

3. 这是常见的做法吗?

这绝对是SSH远程执行复杂命令的标准常规做法。
只要远程命令包含空格、管道、正则表达式这类特殊字符,就必须用引号包裹命令段——如果不用,本地shell会提前解析这些特殊字符,比如把ssh user@host lscpu | grep '^CPU'里的管道当成本地操作,先跑远程的lscpu再在本地过滤结果,完全不符合脚本预期。用双引号包裹远程命令段是保证远程命令按计划执行的基础操作。

内容的提问来源于stack exchange,提问作者dylosaur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:11:32