在 ssh 命令中使用 shell 变量的未定义变量
undefined variable using a shell variable in a ssh command
我是 bash 脚本的新手,可能不会经常这样做。我有以下脚本来检查某个位置的最新更新,但我得到:
location: Undefined variable
并且时间戳未成功检索。
#!/bin/bash
servers=('x' 'y')
results=()
location="/path/to/location/"
for server in "${servers[@]}"; do
output=$(ssh "$server" 'find "${location}" -exec stat \{} --printf="%y\n" \; | sort -n -r | head -n 1')
x=(${server}:${output})
results+=(${x})
done
echo "Printing results..."
for res in "${results[@]}"; do
echo "$res"
done
我的目标是在最后打印:
x:<timestamp of last update>
y:<timestamp of last update>
我想知道怎么了。
这里的直接问题是 'foo "$bar"'
在单引号内仍然有 bar
的扩展(这使得双引号成为文字,而不是句法)。这不是一件坏事——文字引号,当传递给 ssh
时,可以被 ssh 连接远程端的 shell 接受——但它有副作用 $location
未展开;因此,对 "${location}"
的引用使其成为未定义的远程 shell。
为 eval
生成正确转义命令或作为参数传递给 ssh
的最佳方法是让 shell 为您完成。在目前的情况下,看起来有点像这样:
printf -v cmd1 '%q ' find "$location" -exec stat --printf='%y\n' '{}' +
ssh "$server" "$cmd1 | sort -n -r | head -n 1"
管道组件未包含在 cmd1
中,因为 -- 在将内容转义为数据而不是语法时 -- printf %q
会导致文字 |
个字符成为作为参数传递给 find
而不是作为 shell 指令。 (这正是您 想要 它对 $location
中的任何文字内容所做的,否则这些文字内容可能会被 运行 作为命令使用!)。
这样,shell 本身(通过 printf %q
的魔力)将负责扩展变量并正确转义您的 find
命令,以确保内容被视为数据(即 '/tmp/$(rm -rf /)'
的 location
不会删除文件)。
我是 bash 脚本的新手,可能不会经常这样做。我有以下脚本来检查某个位置的最新更新,但我得到:
location: Undefined variable
并且时间戳未成功检索。
#!/bin/bash
servers=('x' 'y')
results=()
location="/path/to/location/"
for server in "${servers[@]}"; do
output=$(ssh "$server" 'find "${location}" -exec stat \{} --printf="%y\n" \; | sort -n -r | head -n 1')
x=(${server}:${output})
results+=(${x})
done
echo "Printing results..."
for res in "${results[@]}"; do
echo "$res"
done
我的目标是在最后打印:
x:<timestamp of last update>
y:<timestamp of last update>
我想知道怎么了。
这里的直接问题是 'foo "$bar"'
在单引号内仍然有 bar
的扩展(这使得双引号成为文字,而不是句法)。这不是一件坏事——文字引号,当传递给 ssh
时,可以被 ssh 连接远程端的 shell 接受——但它有副作用 $location
未展开;因此,对 "${location}"
的引用使其成为未定义的远程 shell。
为 eval
生成正确转义命令或作为参数传递给 ssh
的最佳方法是让 shell 为您完成。在目前的情况下,看起来有点像这样:
printf -v cmd1 '%q ' find "$location" -exec stat --printf='%y\n' '{}' +
ssh "$server" "$cmd1 | sort -n -r | head -n 1"
管道组件未包含在 cmd1
中,因为 -- 在将内容转义为数据而不是语法时 -- printf %q
会导致文字 |
个字符成为作为参数传递给 find
而不是作为 shell 指令。 (这正是您 想要 它对 $location
中的任何文字内容所做的,否则这些文字内容可能会被 运行 作为命令使用!)。
这样,shell 本身(通过 printf %q
的魔力)将负责扩展变量并正确转义您的 find
命令,以确保内容被视为数据(即 '/tmp/$(rm -rf /)'
的 location
不会删除文件)。