Tôi đang làm việc trên một tập lệnh đã trở nên phức tạp đến nỗi tôi muốn đưa vào một tùy chọn dễ dàng để cập nhật nó lên phiên bản mới nhất. Đây là cách tiếp cận của tôi:Đây có phải là phương pháp tự cập nhật hợp lệ cho tập lệnh bash không?
set -o errexit
SELF=$(basename $0)
UPDATE_BASE=http://something
runSelfUpdate() {
echo "Performing self-update..."
# Download new version
wget --quiet --output-document=$0.tmp $UPDATE_BASE/$SELF
# Copy over modes from old version
OCTAL_MODE=$(stat -c '%a' $0)
chmod $OCTAL_MODE $0.tmp
# Overwrite old file with new
mv $0.tmp $0
exit 0
}
Kịch bản dường như hoạt động như dự định, nhưng tôi tự hỏi liệu có thể cẩn thận với cách tiếp cận này không. Tôi chỉ có một thời gian khó tin rằng một kịch bản có thể tự ghi đè lên mà không có bất kỳ hậu quả nào.
Để rõ ràng hơn, tôi tự hỏi, nếu, có thể, bash sẽ đọc và thực thi tập lệnh từng dòng và sau mv
, thì exit 0
có thể là thứ khác từ tập lệnh mới. Tôi nghĩ rằng tôi nhớ Windows hoạt động như vậy với các tệp .bat
.
Cập nhật: Đoạn mã gốc của tôi không bao gồm set -o errexit
. Theo sự hiểu biết của tôi, điều đó sẽ giữ cho tôi an toàn khỏi các vấn đề gây ra bởi wget
.
Ngoài ra, trong trường hợp này, UPDATE_BASE
trỏ đến một vị trí trong điều khiển phiên bản (để giảm bớt lo ngại).
quả: Dựa trên những thông tin từ những câu trả lời, tôi xây dựng cách tiếp cận này được sửa đổi:
runSelfUpdate() {
echo "Performing self-update..."
# Download new version
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."
# Copy over modes from old version
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
# Spawn update script
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
}
nó sẽ không thể tốt hơn để thay thế 'thoát 0' với 'exec "$ 0"' cộng với bất kỳ đối số bạn cần để chuyển tiếp (có thể: 'exec "$ 0" "$ @" ')?Đó là, sau khi giao dịch với các cơ chế tải xuống, xác minh và thay thế hóa thân trước đó của tập lệnh như được thảo luận bởi @shellter. –
@JonathanLeffler Có, có thể. Bây giờ, tôi muốn giữ một hành động riêng biệt và ngắn gọn để nó không thể can thiệp vào phần còn lại của kịch bản. Khi tôi tự tin vào cách tiếp cận này, tôi có thể mở rộng nó. –
Lưu ý rằng việc cho phép với stat yêu cầu một cờ và định dạng khác trên osx. Tương đương là 'stat -f'% A '$ 0'. – meonlol