launchd 和 click

Technology , ,

起因是看了一篇介绍 Beancount博文后,我就变成了数豆狂魔,大概是心底某种控制欲被激发了出来,没事就喜欢打开 fava 研究自己那点生活补贴流向哪里了。每次开 fava 前都需要在终端里现开启之,有点麻烦,于是我就想让它一直运行在后台。在 macOS 上开启一个程序并让它一直运行在后台的方法自然是用 launchd,我很快就写好了配置文件:

<?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>lencerf.fava</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/bin/fava</string>
      <string>/Users/Lencerf/Dropbox/Application Data/BeanCount/main.bean</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
  </dict>
</plist>

然而 launchctl load fava.plist 后在浏览器里访问 http://localhost:5000/ 却毫无反应。完全想不出问题出在哪里,本着控制变量的原则,我先尝试一下 bean-web。把 /usr/local/bin/fava 换成 /usr/local/bin/bean-web 后访问 http://localhost:8080/,可以打开 bean-web 页面,说明问题在 fava 身上。

但是 fava.plist 加载之后 fava 运行在后台,看不到任何输出信息,如何 debug 呢?Google 之后找到了办法,这个页面上提供了几个解决办法,我采用的第二个办法,指定输出到文件,在上面的 plist 文件中加入几个键值:

<key>StandardOutPath</key>
<string>/path/to/logfile.log</string>
<key>StandardErrorPath</key>
<string>/path/to/error.log</string>

于是当我打开再次 launchctl load fava.plist 后,在 error.log 中看到了大量这样的输出:

Traceback (most recent call last):   File "/usr/local/bin/fava", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.5/site-packages/click/core.py", line 716, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/click/core.py", line 675, in main
    _verify_python3_env()
  File "/usr/local/lib/python3.5/site-packages/click/_unicodefun.py", line 119, in _verify_python3_env
    'mitigation steps.' + extra)
RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII as encoding for the environment.  Either run this under Python 2 or consult http://click.pocoo.org/python3/ for mitigation steps.

This system lists a couple of UTF-8 supporting locales that
you can pick from.  The following suitable locales where
discovered: af_ZA.UTF-8, am_ET.UTF-8, be_BY.UTF-8, bg_BG.UTF-8, ca_ES.UTF-8, cs_CZ.UTF-8, da_DK.UTF-8, de_AT.UTF-8, de_CH.UTF-8, de_DE.UTF-8, el_GR.UTF-8, en_AU.UTF-8, en_CA.UTF-8, en_GB.UTF-8, en_IE.UTF-8, en_NZ.UTF-8, en_US.UTF-8, es_ES.UTF-8, et_EE.UTF-8, eu_ES.UTF-8, fi_FI.UTF-8, fr_BE.UTF-8, fr_CA.UTF-8, fr_CH.UTF-8, fr_FR.UTF-8, he_IL.UTF-8, hr_HR.UTF-8, hu_HU.UTF-8, hy_AM.UTF-8, is_IS.UTF-8, it_CH.UTF-8, it_IT.UTF-8, ja_JP.UTF-8, kk_KZ.UTF-8, ko_KR.UTF-8, lt_LT.UTF-8, nl_BE.UTF-8, nl_NL.UTF-8, no_NO.UTF-8, pl_PL.UTF-8, pt_BR.UTF-8, pt_PT.UTF-8, ro_RO.UTF-8, ru_RU.UTF-8, sk_SK.UTF-8, sl_SI.UTF-8, sr_YU.UTF-8, sv_SE.UTF-8, tr_TR.UTF-8, uk_UA.UTF-8, zh_CN.UTF-8, zh_HK.UTF-8, zh_TW.UTF-8

看上去和 click 这个 Python 包有点关系,搜索了一番,看了看这个 issue,猜想可能和没有指定语言有关系,看来需要想办法在 fava.plist 中指定相关的环境变量,

<key>EnvironmentVariables</key>
<dict>
    <key>LANG</key>
    <string>en_US.UTF-8</string>
</dict>

再次加载,成功!

(实际解决问题的过程比这复杂多了,中间走了歪路差不多把 /usr/local/bin/fava 自己写了一遍。真是大大的 bgm38