【问题标题】:Converting a Shell Script Into a *.app File将 Shell 脚本转换为 *.app 文件
【发布时间】:2015-08-27 20:15:10
【问题描述】:

使用 Automator.app 和 Platypus.app,我已经能够捆绑一个简单的 shell 脚本,用于在我的 MacBook Pro 上重启 wi-fi。两个生成的应用程序都运行正常,但有一个我想纠正的明显问题:应用程序从程序外部引用 shell 脚本。如何嵌入 shell 脚本并从应用的资源中引用它,以便即使原始源文件被移动,应用也可以运行?

【问题讨论】:

标签: macos shell scripting executable desktop


【解决方案1】:

顺便提一下,如果您在脚本上获取信息,您可以将其设置为使用终端打开。这将在您双击它时运行脚本。

否则,将脚本打包到 .app 包中是微不足道的。 Mac OS X 将愉快地运行任何标识为应用程序可执行文件的脚本。

至少,您需要以下结构:

  • (名称).app
    • 内容
      • MacOS
        • (姓名)

名为 (name) 的文件是您的脚本(必须 是可执行的,并且必须 有一个 shebang 行)。 .app 目录和脚本文件中的(名称)必须相同:例如,如果您的应用程序目录名为“My Shell Script.app”,则 MacOS 目录中的文件必须名为“My Shell Script”,并带有无扩展名

如果这样做不方便,可以使用 Info.plist 文件来指定备用可执行文件名称。 Info.plist 进入 Contents 目录:

  • Wrapper.app
    • 内容
      • Info.plist
      • MacOS
        • MyScript

如果您在属性列表中将 MyScript 指定为 CFBundleExecutable,则此结构(在名为 Wrapper.app 的包装器中的 MyScript 可执行文件)有效:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleExecutable</key>
    <string>MyScript</string>
</dict>
</plist>

使用 Info.plist 文件可能更可取,因为这将允许您重命名包装器而不会破坏它。

这是一个使用/bin/sh 作为解释器的示例脚本,但你真的可以拥有任何东西(#!/usr/bin/swift#!/usr/bin/python 等)。

#!/bin/sh
open -a Calculator

脚本将在您双击应用程序包时运行。

您可以在Contents 目录中将您需要的任何其他内容与您的脚本捆绑在一起。如果您喜欢,可以使用 Resources 目录之类的东西重现标准的可执行包布局。

【讨论】:

  • 这个文件结构不被认为是 PowerPC 应用程序吗?如果是这样,则它们自 10.7 发布以来一直不受支持。
  • 据我所知,应用程序的架构一直是由可执行头而不是包的结构来标识的,并且 PPC 支持在 10.6 中被删除,而没有任何改变。无论哪种方式,如果您担心的话,这在我的 Yosemite 设置上运行良好。
  • 几乎没有 391K。你里面只有这些吗?你有没有考虑过用这个和 shebang 线从头开始编写一个新脚本?
  • 虽然这行得通;我只想指出,您不能使用 MacOS 中的脚本对包进行代码签名。 MacOS 目录中的非 Mach-O 文件不维护代码签名。有关详细信息,请参阅 Apple 的代码签名指南:developer.apple.com/library/content/documentation/Security/…
  • @Daniel,如果我没记错的话,macOS 使用 Apple 事件来告诉你的程序打开一个文档。您将无法从 shell 脚本接收这些内容。可以通过可以访问本机库的脚本语言来实现。
【解决方案2】:

虽然这可行,但似乎无法从脚本访问 Contents 目录。它没有将环境变量传递给 bash 或我能找到的任何其他地方。这使得很难将内容捆绑到 Contents 目录中,因为 bash 脚本似乎无法访问它。网上有各种 hack,但它们都涉及通过名称有效地搜索脚本,这意味着如果在两个地方有两个版本的应用程序,那么它将失败。 有人解决了吗?

【讨论】:

  • bash 脚本中“$0”的值是多少?如果它包含完整路径,您可以使用 dirname 进入 Contents 文件夹。
  • 我得到了它与$(cd "$(dirname "$0")"; pwd)的合作
猜你喜欢
  • 2016-04-28
  • 1970-01-01
  • 2012-12-31
  • 2014-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
相关资源
最近更新 更多