![如何在单引号或双引号内扩展变量](https://linux22.com/image/223029/%E5%A6%82%E4%BD%95%E5%9C%A8%E5%8D%95%E5%BC%95%E5%8F%B7%E6%88%96%E5%8F%8C%E5%BC%95%E5%8F%B7%E5%86%85%E6%89%A9%E5%B1%95%E5%8F%98%E9%87%8F.png)
我有 2 个系统,它们具有相同的目录结构。我想在本地系统上执行几个命令,并在远程系统上执行相同的命令。
我使用通配符,因此当我有新版本的包时,我不需要再次编辑 bash 脚本!
我的 bash 脚本有这样几行:
varWheelsDir="/tmp/wheels"
set -x
# Install local
pip3 install --force-reinstall --user "${varWheelsDir}/bbw"*
# Install remote
ssh -t admin@otherhost "pip3 install --user '${varWheelsDir}/bbw$*'"
这也展开
+ pip3 install --user /tmp/wheels/bbw-2.10.0-py3-none-any.whl
+ ssh -t admin@otherhost 'pip3 install --user '\''/tmp/wheels/bbw'\'''
显然,SSH 线路的扩展不起作用。
知道如何将其输入ssh -t
答案1
显然,SSH 线路的扩展不起作用。
撇开该语句中的语法问题不谈,扩展“不起作用”这一点并不明显,只是它没有达到您的预期。如果您包含了它是如何扩展的以及您期望什么,那将会有所帮助。
我怀疑您的意思是您希望扩展发生在远程主机上而不是 ssh 客户端上。在这种情况下,您只需转义传递给本地 shell 的参数 - 但您还需要更改引用以允许远程扩展:
ssh -t admin@otherhost "pip3 install --user \"\${varWheelsDir}/bbw\*\""
答案2
您必须检查当 ssh 命令为“build”时扩展了哪些部分,结果是什么,以及在远程主机上执行该命令时扩展了哪些内容。
对于您的第一次尝试
ssh -t admin@otherhost "pip3 install --user '${varWheelsDir}/bbw$*'"
# expands to
ssh -t admin@otherhost "pip3 install --user '/tmp/wheels/bbw'"
# and executes on the other host
pip3 install --user '/tmp/wheels/bbw'
$*
扩展到位置参数,这里可能没有。看https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html#index-_002a
如果你这样做
ssh -t admin@otherhost "pip3 install --user '${varWheelsDir}/bbw'*"
# it should expand to
ssh -t admin@otherhost "pip3 install --user '/tmp/wheels/bbw'*"
# which executes on the other host
pip3 install --user '/tmp/wheels/bbw'*
(请注意, is*
位于双引号内以防止在本地主机上进行通配,但位于单引号之外以在远程主机上进行文件通配)
我厌倦了
x=/tmp
ssh -t otherhost "ls -l '$x/'*"
为我工作并列出了远程主机上 temp 中的所有目录。
答案3
许多系统都有AcceptEnv LC_*
其sshd
配置,因此您可以执行以下操作:
export LC_DIR="$varWheelsDir"
shell_code='
pip3 install --force-reinstall --user "$LC_DIR"/bbw*
'
eval "$shell_code" # interpreted by current shell
ssh -e SendEnv=LC_DIR -t admin@otherhost "$shell_code"
# interpreted by the login shell of admin on otherhost,
# assuming it is Bourne-like
使用相同的 shell 代码在本地和远程运行,并共享$LC_DIR
具有相同内容的变量。
或者,如果本地 shell 是 zsh 并且您知道admin
on的登录 shell 与 Bourne 类似,则可以构造 shell 代码,其中以安全的方式嵌入和引用otherhost
本地变量的内容:$varWheelsDir
pip3 install --force-reinstall --user "${varWheelsDir}"/bbw* # local
ssh -t admin@otherhost "
pip3 install --force-reinstall --user ${(qq)varWheelsDir}/bbw"* # remote
where使用单引号引用 sh 语法中${(qq)var}
的内容($var
引用任意数据的最安全形式)。
最新版本的bash
具有${var@Q}
扩展$var
、引用的运算符,但在某些情况下它会生成不可移植的 bash 特定语法,并且不仅使用单引号,因此只有当admin
on的登录 shellotherhost
碰巧是bash
(最好是相同的版本并在相同的区域设置中运行)。
如果您不能保证admin
on的登录 shellotherhost
与 Bourne 类似,请参阅如何在不知道远程用户的登录 shell 的情况下通过 ssh 执行任意简单命令?可能的方法。