LaunchDaemon 运行 Python 的不同实例到终端

LaunchDaemon runs different instance of Python to terminal

使用具有以下 plist 的 LaunchDaemon:

<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
            <string>com.test.testing</string>
        <key>ProgramArguments</key>
            <array>
                <string>python3</string>
                <string>/Users/my-name/python-daemon/python_daemon_test.py</string>
            </array>
        <key>StandardErrorPath</key>
            <string>/var/log/test-Error.log</string>
        <key>StandardOutPath</key>
            <string>/var/log/test.log</string>
        <key>RunAtLoad</key>
            <true/>
    </dict>
    </plist>

要启动的脚本所在的位置

#!/usr/bin/env python3

import sys
print(sys.version)
print(sys.path)

我有一些我不理解的行为。

当我在终端中 运行 脚本时(which python3 结果为 /Users/my-name/opt/anaconda3/bin/python3),我收到以下输出:

3.7.4 (default, Aug 13 2019, 15:17:50)
[Clang 4.0.1 (tags/RELEASE_401/final)]
['/Users/my-name/python-daemon', '/Users/my-name/opt/anaconda3/lib/python37.zip', 
'/Users/my-name/opt/anaconda3/lib/python3.7', 
'/Users/my-name/opt/anaconda3/lib/python3.7/lib-dynload', 
'/Users/my-name/.local/lib/python3.7/site-packages', 
'/Users/my-name/opt/anaconda3/lib/python3.7/site-packages', 
'/Users/my-name/opt/anaconda3/lib/python3.7/site-packages/aeosa']

这是我想要的,因为我希望 运行 的实际(非玩具)脚本使用我在 Anaconda 中安装的 PyObjc 包。

但是,当脚本被 LaunchDaemon 运行 时,我在 test.log 文件中得到以下内容:

3.7.3 (default, Mar  6 2020, 22:34:30) 
[Clang 11.0.3 (clang-1103.0.32.29)]
['/Users/my-name/python-daemon', 
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python37.zip', 
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7', 
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/lib-dynload', 
'/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/site-packages']

这是一个问题,因为我希望 运行 的实际脚本取决于 Anaconda 中的一个包。我曾预计,由于脚本中的第一个程序参数是 python3,它将 运行 与终端中的 python3 相同,但我错了。

为什么脚本会这样? 我想这可能是因为它 运行 的脚本是 sudo,但 sudo which python3 也是 returns 通往 Anaconda 的路径。

我该如何解决这个问题?我确信一个简单的解决方案是将我想要的包安装在 Xcode 版本 Python3 中的某处。但是,我实际上不确定该怎么做。它也会让人感到有点不满意,因为我想知道为什么 LaunchDaemons 会这样。

Launch Daemons(以及 cron 作业和...)不会 运行 在您通常的 Terminal/shell 环境下,因此它们不会获得任何自定义、附加组件等设置在您的 Terminal/shell 环境中。特别是,它们不 运行 各种 shell 初始化脚本(~/.bash_profile、~/.bashrc 等)通常具有要设置的命令改善您的环境。

在 anaconda 的特定情况下,它的安装程序会在您的 ~/.bashrc 文件中添加一个部分,以将 anaconda 二进制文件目录添加到 PATH,并且可能还有一些其他更改。这会影响您的环境,您在终端中的 bash 会话,但不会对启动代理生效,甚至不会影响其他 shell 中的终端会话 ()。

对于 Launch Daemon,我建议不要将其 运行 作为您的 shell 安装脚本——这些是您的个人配置,与 [=44] 无关=] 由系统进程。相反,我会创建一个简短的 shell 脚本,其中包含相关设置(从您的 ~/.bashrc 复制)和 then 运行 是您的 python 脚本。然后更改 Launch Daemon,使其 运行 使用该脚本,而不是直接 运行 使用 python 脚本。

P.S。由于脚本在启动 python 脚本后不必执行任何操作,因此在这种情况下脚本可以使用 exec 命令自行退出,而 运行 python 脚本而不是 在同一进程中 。这意味着 python 将是 launchd 的直接子进程,并且 launchd 可以按照自己喜欢的方式监视、控制等。 (这与正常使用脚本 运行 python 相反,在这种情况下,您将有一个现在毫无意义的 shell 进程挂起等待 python 脚本完成以便它可以完成。)

所以我会用以下内容结束脚本:

exec python3 /Users/my-name/python-daemon/python_daemon_test.py