【问题标题】:How can I silently install a MacOS .app from a dmg, using a single command?如何使用单个命令从 dmg 静默安装 MacOS .app?
【发布时间】:2019-09-16 02:05:26
【问题描述】:

我正在为我的跨平台应用程序编写一个自动更新工具。更新程序部分下载安装程序文件并执行 shell 命令来安装它。在 MacOS 上,我们的“安装程序”采用 .dmg 文件的形式。我需要能够静默挂载磁盘映像,将包含的.app(s) 复制/覆盖到目标目录,然后卸载磁盘映像。我假设磁盘映像包含一个可以直接复制到/Applications 或其他地方的包。没有明智的方法将任意的.dmg 文件作为asked before 处理,因为它的内容是未知的。必须做出一些假设。

【问题讨论】:

  • 不,这是一个不同的(而且不好的)问题。那是在询问如何从命令行安装 dmg。 dmg 不是 /can/ 可以安装的东西,它只是一个磁盘映像,如 .iso。我特别想安装一个包含在 .dmg 中的 .app。 stackexchange 问题的 /answers/ 稍好一些,但问题本身也不好,原因同上。

标签: macos command-line terminal dmg .app


【解决方案1】:
VOLUME=$(hdiutil attach -nobrowse '[DMG FILE]' |
    awk 'END {$1=$2=""; print $0}'; exit ${PIPESTATUS[0]}) &&
(rsync -a "$VOLUME"/*.app /Applications/; SYNCED=$?
    (hdiutil detach -force -quiet "$VOLUME" || exit $?) && exit "$SYNCED")

我会分解一下:

  • hdiutil attach -nobrowse '[DMG FILE]'挂载磁盘镜像,但不显示在桌面上
  • | awk 'END {$1=$2=""; print $0}' 丢弃 hdiutil 输出的前两个标记,留下剩余部分,即挂载的卷
  • VOLUME=$(...; exit ${PIPESTATUS[0]})VOLUME 设置为上面的输出,并将退出代码设置为hdiutil
  • &&如果磁盘镜像挂载成功...
  • rsync -a "$VOLUME"/*.app /Applications/ ...使用rsync 将.app 文件复制到/Applications 目录,同时保留权限/符号链接/所有权等。
  • ; SYNCED=$?存储rsync操作的结果
  • (hdiutil detach -force -quiet "$VOLUME"强制卸载磁盘镜像
  • || exit $?) && "$SYNCED" 使用 hdiutil 退出代码退出,如果 hdiutil 成功,则 rsync 退出代码

【讨论】:

  • 把这个放在双引号里对我来说是错误的; calling shell 将在bash -c 开始运行之前扩展$VOLUME。 (为什么还要在单独的 Bash 实例中运行它?)
  • 另外,不要对私有变量使用大写。
  • 因为如果我只是裸机运行它,它将使用用户的 shell 设置的任何内容。很可能是 bash,但也可能不是。不过,双引号很好。
  • 括号可能会改为大括号以避免子shell。您还需要在右大括号之前添加一个分号(这是 POSIX shell 语法中的一个奇怪的特质)。
  • 对挂载目录包含空格时的小改进,当前的awk 只会给我们部分路径,将其更改为awk 'END {$1=$2=""; print $0}' 以忽略前两个匹配项,并采取其余的:VOLUME=$(hdiutil attach -nobrowse '[DMG FILE]' | awk 'END {$1=$2=""; print $0}'; exit ${PIPESTATUS[0]}) && (rsync -a "$VOLUME"/*.app /Applications/; SYNCED=$? (hdiutil detach -force -quiet "$VOLUME" || exit $?) && exit "$SYNCED")
猜你喜欢
  • 2011-09-15
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
  • 2012-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多