有时候需要维护一个可以自升级的 shell 程序,先考虑下面这个:
[Bash shell] 纯文本查看 复制代码 set -o errexit #有错误则退出
SELF=$(basename $0)
UPDATE_BASE=http://something
runSelfUpdate() {
echo "Performing self-update..."
# 下载新版本
wget --quiet --output-document=$0.tmp $UPDATE_BASE/$SELF
# 从旧版本那里获取设置属性
OCTAL_MODE=$(stat -c '%a' $0)
chmod $OCTAL_MODE $0.tmp
# 用新版本覆盖旧版本
mv $0.tmp $0
exit 0
}
这个自升级的脚本可能在许多情况下没有问题,但是仍潜在不可预料性。因为它直接覆盖的是一个正在打开并运行的脚本,这种做法在 Windows 上是不被允许的。
修正上面的脚本如下:
[Bash shell] 纯文本查看 复制代码 runSelfUpdate() {
echo "Performing self-update..."
# 下载新版本
echo -n "Downloading latest version..."
if ! wget --quiet --output-document="$0.tmp" $UPDATE_BASE/$SELF ; then
echo "Failed: Error while trying to wget new version!"
echo "File requested: $UPDATE_BASE/$SELF"
exit 1
fi
echo "Done."
# 复制旧版本的设置属性
OCTAL_MODE=$(stat -c '%a' $SELF)
if ! chmod $OCTAL_MODE "$0.tmp" ; then
echo "Failed: Error while trying to set mode on $0.tmp."
exit 1
fi
# 这里做一个升级脚本
cat > updateScript.sh << EOF
#!/bin/bash
# Overwrite old file with new
if mv "$0.tmp" "$0"; then
echo "Done. Update complete."
rm \$0
else
echo "Failed!"
fi
EOF
echo -n "Inserting update process..."
exec /bin/bash updateScript.sh # exec 将父进程去掉,完全切入到子进程中,所以不会有上述的覆盖一个正在运行的脚本的潜在危险性
}
|