Managing User Services for Python Applications
About venvRun.sh
It is important to ensure any automated tasks being run are aware of already-running instances of itself, so it can prevent creating additional instances which would otherwise begin stacking or fighting over finite resources such as a listening socket, etc.
Host Networks are providing venvRun.sh
as an example script to demonstrate using just one of various methods for handling the task of running a headless script, meaning it runs without being tied to any remote logged in session.
Additionally it handles automatically re-starting the python script should it close, crash, or quit for any reason.
Feel free to change it to suit your preferences as desired.
Create venvRun.sh
for the account
SSH in and run the following command to create the management script in the account's home directory:
fn="${HOME}/venvRun.sh";[ -f "${fn}" ]&&echo "${fn} exists already."||curl -L "https://faq.hostnetworks.com.au/static/src/venvRun.sh" -o "${fn}";chmod 755 "${fn}"
Alternative Copy-Paste method of installing script:
[ -f "${HOME}/venvRun.sh" ]&&echo "${HOME}/venvRun.sh already exists, not proceeding."||echo '#!/usr/bin/env bash if [ ${#} -eq 0 ]; then echo "No virtualenv name provided, cannot continue without a valid virtualenv name." else venvName="${1}"; shift pyScriptArgs="" if [ $# -gt 0 ]; then pyScriptArgs="${*}" fi scriptName="${BASH_SOURCE##*/}" PIDFILE="/tmp/${scriptName}.${venvName}.pid" myPID="${$}" venvPyDIR="${HOME}/virtualenv/${venvName}" pyVerStr="$(find "${venvPyDIR}" -maxdepth 1 -type d -iname '?.?')";pyVer="${pyVerStr##*/}" venvPyBIN="${pyVerStr}/bin/python${pyVer}" myPath="${PWD}" pyScript="${pyScriptArgs}" [ -f "${pyScript}" ]&&myPath="${pyScript%/*}" # test if pyScriptArgs exists as a file & cd to the full path (preceding the final '/') of our absolute filepath string if [[ -e "${PIDFILE}" ]]; then # check for, and create a PID FILE if it does not already exist: echo "PID FILE: \"${PIDFILE}\" exists, and contains the following: \"$(cat "${PIDFILE}")\"" else echo "PID FILE: \"${PIDFILE}\" not found, creating new PID FILE containing the following PID: \"${myPID}\"..." echo "${myPID}" > "${PIDFILE}" fi chmod 660 "${PIDFILE}" # ensure pid file contents are not readable to everyone, just this user and group if [ "$(cat "${PIDFILE}")" == "${myPID}" ]; then echo "${PIDFILE} contains the following PID: \"$(cat "${PIDFILE}")\"" echo "First-time run detected (our current PID matches PIDFILE) - Initiating start-up..." echo; echo "HELPFUL REMINDER/TIP: To run this as an automatically self-recovering service simply add the following to your crontab:" echo "venvName=\"${venvName}\"; pyScript=\"${pyScriptArgs}\"; ${PWD}/${scriptName} \${venvName} \${pyScript} >/dev/null 2>&1"|sed -E "s/\/home\/${USER}/\${HOME}/g"; echo cd "${myPath}";"${venvPyBIN}" ${pyScriptArgs} echo "Python script has now exited. Removing PID FILE and stopping." rm "${PIDFILE}" else echo "\"${PIDFILE}\" contains the following PID: \"$(cat "${PIDFILE}")\"" echo "Current PID: \"${myPID}\" differs from the above; confirming that our python service is running:" pyPID="$(pgrep -f "${venvPyBIN}")" if [ "${pyPID}" == "" ]; then echo "No python processes found, cleaning up PIDFILE then exiting." rm "${PIDFILE}" else echo "Found the following python PID: \"${pyPID}\", no further action required, exiting." fi fi fi' > "${HOME}/venvRun.sh";chmod 755 "${HOME}/venvRun.sh"
Before Using venvRun.sh
First create a new Python Web Application
in cPanel
:
Provide the desired name for the Application root, in this example we have chosen
pyHttpd
Click CREATE
then move on to Using venvRun.sh
below.
Using venvRun.sh
On the first-time run it is recommended to perform an interactive test run from SSH shell:
NB: The venvRun.sh script expects the name of the Python App created earlier, and either the path to the python script to be run, or a short string of python arguments to run directly.
For this example we will simply call a built-in python3 module to run:
~/venvRun.sh pyHttpd -m http.server 8000 --directory ${HOME}/pyshare
Output of ~/venvRun.sh
command:
[demo@example.com ~]$ ~/venvRun.sh pyHttpd -m http.server 8000 --directory ${HOME}/pyshare PID FILE: "/tmp/venvRun.sh.pyHttpd.pid" not found, creating new PID FILE containing the following PID: "3079860"... /tmp/venvRun.sh.pyHttpd.pid contains the following PID: "3079860" First-time run detected (our current PID matches PIDFILE) - Initiating start-up... HELPFUL REMINDER/TIP: To run this as an automatically self-recovering service simply add the following to your crontab: venvName="pyHttpd"; pyScript="-m http.server 8000 --directory ${HOME}/pyshare"; ${HOME}/venvRun.sh ${venvName} ${pyScript} >/dev/null 2>&1 Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Press Ctrl+C to exit this interactive test run:
^C Keyboard interrupt received, exiting. Python script has now exited. Removing PID FILE and stopping. [demo@example.com ~]$
Complete the new Service with Cronjobs
Now to finalise deploying your service, and enable automatic starting, and self-recovery, simply add the HELPFUL REMINDER/TIP
crontab output from the interactive test run performed earlier:
HELPFUL REMINDER/TIP: To run this as an automatically self-recovering service simply add the following to your crontab:
venvName="pyHttpd"; pyScript="-m http.server 8000 --directory ${HOME}/pyshare"; ${HOME}/venvRun.sh ${venvName} ${pyScript} >/dev/null 2>&1
After adding this command to run every minute in cPanel
the Current Cron Jobs
should show the following:
Finished!
That's it, you can safely run this venvRun.sh
script without fear of creating duplicate processes, as it detects itself as already running and simply closes.
Further Resources
Still in need of help? For speedy assistance our friendly staff are always ready to help via our helpdesk, on Twitter, through our website, or directly via email to support.