状态码 78 在 launchctl list 的输出中表示该服务启动后进程退出,退出码为 78。这是被管理的程序自身返回的错误码(并非 launchd 的故障),通常是程序未能成功运行或遇到了配置问题。
1. 状态码 78 的含义
launchctl list 显示的结果中,状态列(STATUS)对应服务进程最后一次退出的状态码。78 是常见的自定义退出码,常见于以下情况:
- Python 脚本语法错误:当 Python 解释器遇到语法错误时,会返回非零退出码(通常为 1 或 2),但某些自定义脚本可能会返回 78。
- 端口占用:Flask 开发服务器默认使用 5000 端口,如果端口已被占用,程序退出可能返回特定码。
- 依赖缺失:Python 脚本中
import模块失败,导致异常退出。 - 路径或权限问题:无法找到工作目录、文件无权限、Python 解释器路径错误等。
- 环境变量未设置:脚本需要的环境变量(如
FLASK_APP、PATH)缺失。
2. 排查步骤
2.1 查看服务日志
在 plist 中配置了 StandardOutPath 和 StandardErrorPath,检查这两个文件的内容:
cat ~/myflaskapp/logs/flask.err
cat ~/myflaskapp/logs/flask.log
错误日志中通常会包含 Python 的异常信息,例如:
ModuleNotFoundError: No module named 'flask'
或
OSError: [Errno 48] Address already in use
2.2 手动运行脚本
从终端手动执行 plist 中 ProgramArguments 指定的命令,看是否能正常运行,以及退出码是什么。
cd /Users/yourname/myflaskapp
/Users/yourname/myflaskapp/venv/bin/python3 app.py
如果手动执行时也退出并返回 78,则说明程序本身存在问题。
2.3 检查端口占用
Flask 默认端口 5000,检查是否已被其他进程占用:
lsof -i :5000
如果端口被占用,可以修改 app.run(port=5001) 或 kill 占用进程。
2.4 检查 Python 环境
确认 plist 中使用的 Python 解释器路径是否正确,虚拟环境是否存在且已激活。
ls -l /Users/yourname/myflaskapp/venv/bin/python3
同时,确认脚本中使用的库已安装在虚拟环境中。可尝试在虚拟环境中运行 pip list 检查依赖。
2.5 检查工作目录和文件权限
确保 WorkingDirectory 指定的目录存在且可读,脚本文件有执行权限(通常不需要执行权限,但需可读)。确保日志目录存在且可写。
2.6 检查 plist 语法
运行以下命令检查 plist 文件是否有语法错误:
plutil ~/Library/LaunchAgents/com.yourname.flaskapp.plist
如果输出 OK,则语法正确。
2.7 查看系统日志
如果以上未发现问题,查看 launchd 的系统日志:
log show --predicate 'subsystem == "com.apple.launchd"' --last 1h | grep com.yourname.flaskapp
这可以帮助确认 launchd 在加载或启动服务时是否有错误(例如找不到可执行文件)。
