Here's the lowdown.

  • First, I'm using an EC2 instance with Amazon Linux (the original one, not Amazon Linux 2), limiting me to sysV instead of systemd.
  • I've got a Flask app server running off CherryPy WSGI server with an Nginx reverse proxy in front of it.
  • The WSGI server and app server are all within a python3 virtualenv.
  • The server ran just fine from within the virtualenv.
  • Putting a #! line with the location of the virtualenv python bin at the top of the server file allows me to run the server from anywhere on the system (without first activating the virtualenv) by entering the full path to the server script: /path/to/server.py
  • However, when I try to run this from within an init.d script, I get a ModuleNotFoundError: No module named 'cherrypy' error.
  • I also tried using activate_this.py, to the same outcome.

Here's some (anonymised) code to see if that helps:

server.py:

#!/path/to/myVenv/bin/python

# Activate virtualenv from within this script:
# Commented out as it doesn't seem to help
# activate_this = "/path/to/myVenv/bin/activate_this.py"
# exec(compile(open(activate_this, "rb").read(), activate_this, 'exec'), dict(__file__=activate_this))

# Import your application as:
# from wsgi import application
# Example:

from wsgi import application

# Import CherryPy
import cherrypy

if __name__ == '__main__':

    # Mount the application
    cherrypy.tree.graft(application, "/")

    # Other CherryPy stuff here. Not relevant as script doesn't progress this far
    # when it breaks and works fine when it doesn't

/etc/init.d/crowded (based on https://www.cyberciti.biz/tips/linux-write-sys-v-init-script-to-start-stop-service.html)

#!/bin/bash
#
# chkconfig: 35 90 12
# description: CrowdEd server
#

# Based on file found at
# https://www.cyberciti.biz/tips/linux-write-sys-v-init-script-to-start-stop-service.html

PATH=/path/to/myVenv/bin

# Get function from functions library
. /etc/init.d/functions

# Start the service FOO
start() {
        initlog -c "echo -n Starting CrowdEd server: "
        /path/to/server.py &
        ### Create the lock file ###
        touch /var/lock/subsys/crowded
        success $"CrowdEd server startup"
        echo
}

# Restart the service FOO
stop() {
        initlog -c "echo -n Stopping CrowdEd server: "
        killproc server.py
        ### Now, delete the lock file ###
        rm -f /var/lock/subsys/crowded
        echo
}

### main logic ###
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status crowded
        ;;
  restart|reload|condrestart)
        stop
        start
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart|reload|status}"
        exit 1
esac

exit 0

TL;DR: Python script that works when written from the console doesn't work when called from init.d script, specifically failing to link libraries within the virtualenv when called from init script despite linking them fine when called from the console. I've no idea why.

0

There are 0 best solutions below