获得其他变量扩展的引用 - 美元 - (" $ @")行为?

时间:2014-07-08 05:27:20

标签: bash ssh arguments sh

shell有一个很棒的功能,它可以在你使用“$ @”时保持变量扩展的参数引用,这样脚本就可以了:

for f in "$@"; do echo "$f"; done
使用参数调用时

"with spaces" '$and $(metachars)'

将按字面打印:

with spaces
$and $(metachars)

这不是扩展引用字符串的正常行为,它似乎是“$ @”的特例。

有没有办法让其他变量出现这种行为?在我感兴趣的特定情况下,我希望安全在受限制的公钥条目中的$SSH_ORIGINAL_COMMAND说明符中展开command=,而不必担心参数中的空格,元字符等。

"$SSH_ORIGINAL_COMMAND"会像"$*"那样扩展,即一个天真的扩展,不会在单独的参数周围添加任何引号。

在这种情况下,获取env var SSH_ORIGINAL_COMMAND时,“$ @”样式扩展所需的信息是不可用的?所以我需要说服sshd引用这些论点?

The answer to this question让我想知道它是否有可能。

1 个答案:

答案 0 :(得分:4)

你可以得到类似的"引用的美元在"使用bash arrays "${YOUR_ARRAY_HERE[@]}"语法的任意数组的行为。当然,这还没有完整的答案,因为你仍然必须根据引号将字符串分成多个数组元素。

一种想法是使用bash -x,它会渲染扩展输出,但只有在您实际运行命令时才会这样做;它不能与-n一起使用,这会阻止您实际执行相关命令。同样,您可以使用evalbash -c以及set --来管理引用删除,在外壳上执行扩展以及在内壳上删除引号,但这样做非常难以防范反对执行任意代码。

作为结束运行,请改用xargsxargs handles single and double quotes.这是非常不完美的解决方案,因为xargs处理反斜杠转义字符的方式与bash完全不同,并且完全无法处理分号等等,但如果您的输入相对可预测,则会得到你大部分时间都没有强迫你写一个完整的shell解析器。

SSH_ORIGINAL_COMMAND='foo     "bar  baz"  $quux'

# Build out the parsed array.
# Bash 4 users may be able to do this with readarray or mapfile instead.
# You may also choose to null-terminate if newlines matter.
COMMAND_ARRAY=()
while read line; do
  COMMAND_ARRAY+=("$line")
done < <(xargs -n 1 <<< "$SSH_ORIGINAL_COMMAND")

# Demonstrate working with the array.
N=0
for arg in "${COMMAND_ARRAY[@]}"; do
  echo "COMMAND_ARRAY[$N]: $arg"
  ((N++))
done

输出:

COMMAND_ARRAY[0]: foo
COMMAND_ARRAY[1]: bar  baz
COMMAND_ARRAY[2]: $quux