我对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>
我想知道出了什么问题。
答案 0 :(得分:0)
这里的直接问题是'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
命令,以确保将内容视为数据(即。location
'/tmp/$(rm -rf /)'
./Crashlytics.framework/submit $CRASHLYTICS_API_KEY $CRASHLYTICS_BUILD_SECRET -ipaPath $IPA_PATH
不会删除文件。)