bash - 在 bash 我正在构建一个更新脚本,如何更新更新脚本

标签 bash shell auto-update

我正在构建一个小脚本来更新树莓派上的应用程序文件。

它将执行以下操作:

  1. 下载应用程序文件的 zip 文件
  2. 解压
  3. 将每一个复制到正确的位置,并根据需要使其可执行等。

我遇到的问题是其中一个文件是 updatescript.sh。

我了解到在执行 bash 脚本时更新/更改它是危险的。见 Edit shell script while it's running

有没有什么好方法可以实现我想要做的事情?

最佳答案

您所读到的内容被严重夸大了。

通过 mv在其上覆盖不同的文件来就地覆盖 shell 脚本是完全安全的。 当您这样做时,旧的文件句柄仍然有效,指的是原始未修改的文件内容。您不能安全地做的是就地编辑现有文件。

所以,以下内容很好(并且是所有操作系统供应商更新工具(如 RPM)的实际效果):

#!/usr/bin/env bash
tempfile=$(mktemp "$BASH_SOURCE".XXXXXX)
if curl https://example.com/whatever >"$tempfile" &&
   curl https://example.com/whatever.sig >"$tempfile.sig" &&
   gpgv "$tempfile.sig" "$tempfile"; then
  chown --reference="$BASH_SOURCE" -- "$tempfile"
  chmod --reference="$BASH_SOURCE" -- "$tempfile"
  sync # force your filesystem to fully flush file contents to disk
  mv -- "$tempfile" "$BASH_SOURCE" && rm -f -- "$tempfile.sig"
else
  rm -f -- "$tempfile" "$tempfile.sig"
  exit 1
fi

...虽然这是有风险的:

curl https://example.com/whatever >/usr/local/bin/whatever

所以做第一件事,而不是第二件事:下载脚本的新版本时,将其写入不同的文件,并且仅在下载成功时将其重命名为原始文件。无论如何,这就是你想要做的以确保原子性。

(上面还有一些代码签名验证实践的演示,因为在构建更新程序时需要它们。如果不验证签名,您不会尝试通过自动下载分发代码,对吧? 因为这就是对您的网络服务器的一次简单入侵导致您的每一个客户都被 0 拥有的方式。上面期望您的代码签名 key 的公共(public)方面位于 ~/.gnupg/trustedkeys.gpg,但您可以将 trustedkeys.gpg 放在任何目录中,并使用环境变量 GNUPGHOME 指向它。


即使您没有安全地编写更新代码,风险仍然很容易减轻。如果您将脚本主体移动到函数中,这样就必须完全读取它在执行任何部分之前,文件的任何部分在执行开始时都没有被读取。

#!/usr/bin/env bash
main() {
  echo "Logic all goes here"
}; { main "$@"; exit; }

因为 { main "$@";导出; } 是复合命令的一部分,解析器在开始执行 main 之前读取 exit,因此可以保证不会有更多的源文件内容在 main 退出后读取,即使某些 future 的 bash 版本一开始没有逐行处理输入

关于bash - 在 bash 我正在构建一个更新脚本,如何更新更新脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54101657/

相关文章:

bash - 使用 inotifywait 和 avconv 解释 bash 脚本中的字符串

bash - Bash vi 输入模式中的语法高亮显示

macos - 为什么我的 Ctrl 键在 iTerm.app 中被禁用了?

bash - 如何从输出中删除前两行

asp.net-core - 使用 Asp.Net Core 进行 self 更新/卷影复制

excel - 删除和重新上传数据表而没有引用有 #REF 问题 [Excel]

shell - 命令路径作为 shell 脚本中的变量

linux - 如何求从命令行输入的数字的平均值

linux - 在 bash 中计算文件中的单词出现次数

git - Git 可以用来更新客户端计算机上的软件吗?