【问题标题】:Variables in remote SSH session远程 SSH 会话中的变量
【发布时间】:2017-01-04 01:54:44
【问题描述】:

我的 bash 脚本中有一些不一致的行为。 有变量,并且所有变量都分配了值,我通过在脚本开头回显这些值来确认它们。

但是,当将它们传递给远程 SSH 会话时,一个变量具有值,而另一个变量显示为空白。我很确定我没有覆盖变量的值。

# Script input arguments
USER=$1
SERVER=$2
# Other vars
PFX=$8
#
ADDRESS=$USER@$SERVER

function run {
    ssh $ADDRESS /bin/bash $@
}

# Script body, some stuff happens here
run << "SSHCONNECTION2"
    sudo mv "/home/$USER/$PFX" "/home/$USER/certs/"
SSHCONNECTION2

所以,mv 的输出是

错误 03-Jan-2017 17:20:39 mv:无法将“/home/admin/”移动到其自身的子目录“/home/admin/certs/admin”

谁能给我提示我做错了什么? 谢谢。

【问题讨论】:

  • 当您引用 heredoc 印记时,您是在告诉本地解释器不要扩展 heredoc 中的任何变量。
  • ...因此,使用的只是USERremote 值,而不是本地值。-
  • 这实际上是为什么对自己的变量使用全大写名称是不好的做法的部分原因:这意味着您正在使用与操作系统和 shell 工具共享的相同命名空间,因此您可能会在不知不觉中覆盖(或在不知不觉中使用)对系统其他部分有意义的变量。
  • 参见the POSIX spec on environment variables,指定全大写的变量名用于对系统有意义的变量,并且保留至少一个小写字符的名称供应用程序使用。
  • 哦,顺便说一句——一定要引用"$@";作为裸$@,它的行为方式与$* 完全相同(将所有参数转换为一个字符串,然后将该字符串拆分并返回到一个列表中)。这就是shellcheck.net 会抓住的东西。

标签: bash ssh scripting


【解决方案1】:

USER 有一个远程值,因为USER 总是 有一个值:默认情况下,它是all POSIX systems 上的当前用户帐户。为避免与系统定义的变量名称冲突,您应该为自己的 shell 和环境变量使用小写名称(前者是因为设置名称与环境变量重叠的 shell 变量会隐式覆盖后者)。

#!/bin/bash
#      ^^^^ - not /bin/sh; printf %q (thus, eval-safe quoting) is a bash extension

user=$1
pfx=$8

# Tell the shell to quote your variables to be eval-safe!
printf -v user_q '%q' "$user"
printf -v pfx_q '%q' "$pfx"

# ...then you can use those eval-safe version in your heredoc
run << SSHCONNECTION2
    # because the values are self-quoted, don't put their expansions inside quotes
    sudo mv /home/$user_q/$pfx_q /home/$user_q/certs/
SSHCONNECTION2

注意事项:

  • 刻意不加引号 (SSHCONNECTION2) 以允许扩展发生。
  • 使用小写变量名可避免无意中与对 shell 或系统有意义的名称发生冲突。

上面有点不幸,因为SSHCONNECTION2 heredoc 的文字内容不是可以安全地直接在 shell 中运行的代码。考虑this answer instead

【讨论】:

  • 谢谢你,我会试一试并接受你的回答,我对 bash 还很陌生,现在这很有意义。
猜你喜欢
  • 2015-05-07
  • 2016-01-13
  • 2014-05-21
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多