phantomjs - Why does my Python subprocess error when managed by supervisord? -
i wrote small api screen captures - flask app passes capture requests casperjs using subprocess.popen
in development on mac, , when run server in shell on production server ubuntu 13.04 - works great.
when manage server supervisord, however, subprocess call returns error casperjs cannot find phantomjs (casper runs on phantom).
the error thrown is:
fatal: [errno 2] no such file or directory; did install phantomjs?
the code open source.
here subprocess call:
https://github.com/pwalsh/moment/blob/master/moment/models.py#l215
here supervisor conf file server (i generate actual file fabric, should clear):
https://github.com/pwalsh/moment/blob/master/fabfile/templates.py#l56
there 2 users on system - root, , app's user. when log on machine either of these users, can run dev server successfully, , can run phantomjs , casperjs successfully.
why subprocess error supervisord?
edit: adding code + stacktrace
supervisord conf gunicorn server:
; generated via fabric on 2013-08-18 23:05:50.928087 ; gunicorn configuration moment [program:moment-gunicorn] command=/srv/environments/moment/bin/gunicorn moment:app --bind 127.0.0.1:9000 --workers 4 --timeout 30 --access-logfile /srv/logs/moment_gunicorn_access.log --error-logfile /srv/logs/moment_gunicorn_error.log environment=path="/srv/environments/moment/bin" directory=/srv/projects/moment user=moment autostart=true autorestart=true
the code sends data casperjs/phantomjs subprocess. method of class, full code here:
def capture(self): filename = '{key}.{format}'.format(key=self.get_key().lstrip(self.prefix), format=self.arguments['format']) image = os.path.join(conf.captures_root, filename) params = [conf.casper, conf.capture_script, self.arguments['url'], image, self.arguments['viewport'], self.arguments['target']] casper = subprocess.popen(params, stdout=subprocess.pipe, stderr=subprocess.pipe) casper_output, casper_errors = casper.communicate() logging.info(casper_output) logging.info(casper_errors) logging.info(casper.returncode) # here relying on convention: # if success, subprocess.returncode == 0 # fragile, need investigate. if casper.returncode: raise exception(casper_errors) else: return image
traceback:
warning:root:fatal: [errno 2] no such file or directory; did install phantomjs? warning:root: warning:root:1 error:moment:exception on /capture/ [get] traceback (most recent call last): file "/srv/environments/moment/local/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app response = self.full_dispatch_request() file "/srv/environments/moment/local/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request rv = self.handle_user_exception(e) file "/srv/environments/moment/local/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception reraise(exc_type, exc_value, tb) file "/srv/environments/moment/local/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request rv = self.dispatch_request() file "/srv/environments/moment/local/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) file "/srv/projects/moment/moment/views.py", line 45, in get_capture image = capture.capture() file "/srv/projects/moment/moment/models.py", line 229, in capture raise exception(casper_errors) exception
note:
- i running in virtualenv called "moment", , under user called "moment".
- the error in casper_output variable - first 3 warning warning log when start subprocess
- i note warning raised root - i'd have expected them raised "moment", user supervisord process supposed run as
although (for reasons should investigate) user has escalated original moment
user root
, not mean process has environment present when login shell root.
the chances path set in supervisord.conf
, , that's why phantomjs appears absent.
environments not looked in database of users; instead constructed explicitly setting values (e.g. using script) or inheritance spawning process. in case, inheriting supervisor, , whatever environment supervisor had. if supervisor run cron, environment empty.
best practice in relation supervisor either run using wrapper script sets environment correctly, or explicitly set in supervisord.conf
. recommend latter, unless have common set of environment fixups in file used lot of scripts (such because want run inside virtualenv).