From 4edd2001b38a2af28bec0ad547bea81e1e250455 Mon Sep 17 00:00:00 2001 From: Landon Abney Date: Sat, 28 Mar 2020 16:31:14 -0700 Subject: [PATCH 1/3] Make init scripts Python version agnostic Now that the Tautulli will run on both major versions of Python we can remove the specificity in the init scripts and make them simpler, with the added advantage that some OS's will now run Tautulli through Python 3 instead of Python 2. --- CONTRIBUTING.md | 4 ++-- PlexPy.py | 6 +----- init-scripts/init.fedora.centos.service | 8 ++++---- init-scripts/init.freebsd | 2 +- init-scripts/init.freenas | 2 +- 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b36103b1..e687432e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ All pull requests should be based on the `nightly` branch, to minimize cross mer ### Python Code #### Compatibility -The code should work with Python 2.7. Note that Tautulli runs on many different platforms. +The code should work with Python 2.7.17 or Python 3.6+. Note that Tautulli runs on many different platforms. Re-use existing code. Do not hesitate to add logging in your code. You can the logger module `plexpy.logger.*` for this. Web requests are invoked via `plexpy.request.*` and derived ones. Use these methods to automatically add proper and meaningful error handling. @@ -38,4 +38,4 @@ HTML5 compatible browsers are targeted. * 4 space indentation * `methodName` * `variableName` -* `ClassName` \ No newline at end of file +* `ClassName` diff --git a/PlexPy.py b/PlexPy.py index c583df6c..eb9ceea4 100755 --- a/PlexPy.py +++ b/PlexPy.py @@ -1,8 +1,4 @@ -#!/bin/sh -''''which python >/dev/null 2>&1 && exec python "$0" "$@" # ''' -''''which python2 >/dev/null 2>&1 && exec python2 "$0" "$@" # ''' -''''which python2.7 >/dev/null 2>&1 && exec python2.7 "$0" "$@" # ''' -''''exec echo "Error: Python not found!" # ''' +#!/usr/bin/env python # -*- coding: utf-8 -*- diff --git a/init-scripts/init.fedora.centos.service b/init-scripts/init.fedora.centos.service index fd6b78e8..a9f1d8d2 100755 --- a/init-scripts/init.fedora.centos.service +++ b/init-scripts/init.fedora.centos.service @@ -21,8 +21,8 @@ datadir=/opt/Tautulli configfile=/opt/Tautulli/config.ini pidfile=/var/run/tautulli.pid nice= -# The following line must point to your Python 2.7 install -python27=/usr/src/Python-2.7.11/python +# The following line must point to your Python installation +python=/usr/bin/python ## options=" --daemon --config $configfile --pidfile $pidfile --datadir $datadir --nolaunch --quiet" @@ -30,7 +30,7 @@ options=" --daemon --config $configfile --pidfile $pidfile --datadir $datadir -- start() { # Start daemon. echo -n $"Starting $prog: " - daemon --pidfile=$pidfile $nice $python27 $homedir/Tautulli.py $options + daemon --pidfile=$pidfile $nice $python $homedir/Tautulli.py $options RETVAL=$? echo [ $RETVAL -eq 0 ] && touch $lockfile @@ -39,7 +39,7 @@ start() { stop() { echo -n $"Shutting down $prog: " - killproc -p $pidfile $python27 + killproc -p $pidfile $python RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f $lockfile diff --git a/init-scripts/init.freebsd b/init-scripts/init.freebsd index 6a3a1045..75b6160e 100755 --- a/init-scripts/init.freebsd +++ b/init-scripts/init.freebsd @@ -51,7 +51,7 @@ verify_tautulli_pid() { # Make sure the pid corresponds to the Tautulli process. if [ -f ${tautulli_pid} ]; then pid=`cat ${tautulli_pid} 2>/dev/null` - ps -p ${pid} | grep -q "python2 ${tautulli_dir}/Tautulli.py" + ps -p ${pid} | grep -q "python ${tautulli_dir}/Tautulli.py" return $? else return 0 diff --git a/init-scripts/init.freenas b/init-scripts/init.freenas index 5010d233..a000ea7c 100755 --- a/init-scripts/init.freenas +++ b/init-scripts/init.freenas @@ -51,7 +51,7 @@ verify_tautulli_pid() { # Make sure the pid corresponds to the Tautulli process. if [ -f ${tautulli_pid} ]; then pid=`cat ${tautulli_pid} 2>/dev/null` - ps -p ${pid} | grep -q "python2 ${tautulli_dir}/Tautulli.py" + ps -p ${pid} | grep -q "python ${tautulli_dir}/Tautulli.py" return $? else return 0 From 3f87996bfcfc3060192b17a75427512a33c295a7 Mon Sep 17 00:00:00 2001 From: Landon Abney Date: Sat, 28 Mar 2020 16:58:06 -0700 Subject: [PATCH 2/3] Remove outdated init scripts Remove several init scripts for operating systems that are no longer supported: * `init.ubuntu` would only be useful on Ubuntu 14.04 LTS which has been in ESM for over a year * `init.solaris` is for an operating system that hasn't been updated in >10 years * `init.upstart` is for a startup method Ubuntu attempted but abandoned * `init.fedora.centos.service` is for a version that hasn't recieved updates since 2017-05-10 * `init.freenas` is identical to `init.freebsd` * `init-alt.freebsd` appears to attempt to use the web interface directly, and would break with authentication enabled --- init-scripts/init-alt.freebsd | 88 ---------- init-scripts/init.fedora.centos.service | 76 --------- init-scripts/init.freebsd | 2 +- init-scripts/init.freenas | 81 --------- init-scripts/init.solaris11 | 47 ------ init-scripts/init.ubuntu | 209 ------------------------ init-scripts/init.upstart | 18 -- 7 files changed, 1 insertion(+), 520 deletions(-) delete mode 100755 init-scripts/init-alt.freebsd delete mode 100755 init-scripts/init.fedora.centos.service delete mode 100755 init-scripts/init.freenas delete mode 100755 init-scripts/init.solaris11 delete mode 100755 init-scripts/init.ubuntu delete mode 100755 init-scripts/init.upstart diff --git a/init-scripts/init-alt.freebsd b/init-scripts/init-alt.freebsd deleted file mode 100755 index 7d32bbac..00000000 --- a/init-scripts/init-alt.freebsd +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/sh -# -# PROVIDE: tautulli -# REQUIRE: tautulli -# KEYWORD: shutdown -# -# Add the following lines to /etc/rc.conf.local or /etc/rc.conf -# to enable this service: -# -# tautulli_enable (bool): Set to NO by default. -# Set it to YES to enable it. -# tautulli_user: The user account Tautulli daemon runs as what -# you want it to be. It uses 'tautulli' user by -# default. Do not sets it as empty or it will run -# as root. -# tautulli_dir: Directory where Tautulli lives. -# Default: /usr/local/share/Tautulli -# tautulli_chdir: Change to this directory before running Tautulli. -# Default is same as tautulli_dir. -# tautulli_pid: The name of the pidfile to create. -# Default is tautulli.pid in tautulli_dir. - -. /etc/rc.subr - -name="tautulli" -rcvar=${name}_enable - -load_rc_config ${name} - -: ${tautulli_enable:="NO"} -: ${tautulli_user:="tautulli"} -: ${tautulli_dir:="/usr/local/share/Tautulli"} -: ${tautulli_chdir:="${tautulli_dir}"} -: ${tautulli_pid:="${tautulli_dir}/tautulli.pid"} -: ${tautulli_conf:="${tautulli_dir}/config.ini"} - -WGET="/usr/local/bin/wget" # You need wget for this script to safely shutdown Tautulli. -if [ -e "${tautulli_conf}" ]; then - HOST=`grep -A64 "\[General\]" "${tautulli_conf}"|egrep "^http_host"|perl -wple 's/^http_host = (.*)$/$1/'` - PORT=`grep -A64 "\[General\]" "${tautulli_conf}"|egrep "^http_port"|perl -wple 's/^http_port = (.*)$/$1/'` -fi - -status_cmd="${name}_status" -stop_cmd="${name}_stop" - -command="${tautulli_dir}/Tautulli.py" -command_args="--daemon --quiet --nolaunch --port ${PORT} --pidfile ${tautulli_pid} --config ${tautulli_conf}" - -# Check for wget and refuse to start without it. -if [ ! -x "${WGET}" ]; then - warn "Tautulli not started: You need wget to safely shut down Tautulli." - exit 1 -fi - -# Ensure user is root when running this script. -if [ `id -u` != "0" ]; then - echo "Oops, you should be root before running this!" - exit 1 -fi - -verify_tautulli_pid() { - # Make sure the pid corresponds to the Tautulli process. - pid=`cat ${tautulli_pid} 2>/dev/null` - ps -p ${pid} | grep -q "python ${tautulli_dir}/Tautulli.py" - return $? -} - -# Try to stop Tautulli cleanly by calling shutdown over http. -tautulli_stop() { - if [ ! -e "${tautulli_conf}" ]; then - echo "Tautulli' settings file does not exist. Try starting Tautulli, as this should create the file." - exit 1 - fi - echo "Stopping $name" - verify_tautulli_pid - ${WGET} -O - -q --user=${SBUSR} --password=${SBPWD} "http://${HOST}:${PORT}/shutdown/" >/dev/null - - if [ -n "${pid}" ]; then - wait_for_pids ${pid} - echo "Stopped $name" - fi -} - -tautulli_status() { - verify_tautulli_pid && echo "$name is running as ${pid}" || echo "$name is not running" -} - -run_rc_command "$1" diff --git a/init-scripts/init.fedora.centos.service b/init-scripts/init.fedora.centos.service deleted file mode 100755 index a9f1d8d2..00000000 --- a/init-scripts/init.fedora.centos.service +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh -# -### BEGIN INIT INFO -# Provides: Tautulli -# Required-Start: $all -# Required-Stop: $all -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: starts Tautulli -# Description: starts Tautulli -### END INIT INFO - -# Source function library. -. /etc/init.d/functions - -## Variables -prog=tautulli -lockfile=/var/lock/subsys/$prog -homedir=/opt/Tautulli -datadir=/opt/Tautulli -configfile=/opt/Tautulli/config.ini -pidfile=/var/run/tautulli.pid -nice= -# The following line must point to your Python installation -python=/usr/bin/python -## - -options=" --daemon --config $configfile --pidfile $pidfile --datadir $datadir --nolaunch --quiet" - -start() { - # Start daemon. - echo -n $"Starting $prog: " - daemon --pidfile=$pidfile $nice $python $homedir/Tautulli.py $options - RETVAL=$? - echo - [ $RETVAL -eq 0 ] && touch $lockfile - return $RETVAL -} - -stop() { - echo -n $"Shutting down $prog: " - killproc -p $pidfile $python - RETVAL=$? - echo - [ $RETVAL -eq 0 ] && rm -f $lockfile - return $RETVAL -} - -# See how we were called. -case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status $prog - ;; - restart|force-reload) - stop - start - ;; - try-restart|condrestart) - if status $prog > /dev/null; then - stop - start - fi - ;; - reload) - exit 3 - ;; - *) - echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" - exit 2 -esac diff --git a/init-scripts/init.freebsd b/init-scripts/init.freebsd index 75b6160e..a000ea7c 100755 --- a/init-scripts/init.freebsd +++ b/init-scripts/init.freebsd @@ -60,7 +60,7 @@ verify_tautulli_pid() { # Try to stop Tautulli cleanly by sending SIGTERM tautulli_stop() { - echo "Stopping $name" + echo "Stopping $name." verify_tautulli_pid if [ -n "${pid}" ]; then kill ${pid} diff --git a/init-scripts/init.freenas b/init-scripts/init.freenas deleted file mode 100755 index a000ea7c..00000000 --- a/init-scripts/init.freenas +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh -# -# PROVIDE: tautulli -# REQUIRE: DAEMON tautulli -# KEYWORD: shutdown -# -# Add the following lines to /etc/rc.conf.local or /etc/rc.conf -# to enable this service: -# -# tautulli_enable (bool): Set to NO by default. -# Set it to YES to enable it. -# tautulli_user: The user account Tautulli daemon runs as what -# you want it to be. It uses 'tautulli' user by -# default. Do not sets it as empty or it will run -# as root. -# tautulli_dir: Directory where Tautulli lives. -# Default: /usr/local/share/Tautulli -# tautulli_chdir: Change to this directory before running Tautulli. -# Default is same as tautulli_dir. -# tautulli_pid: The name of the pidfile to create. -# Default is tautulli.pid in tautulli_dir. -PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin" - -. /etc/rc.subr - -name="tautulli" -rcvar=${name}_enable - -load_rc_config ${name} - -: ${tautulli_enable:="NO"} -: ${tautulli_user:="tautulli"} -: ${tautulli_dir:="/usr/local/share/Tautulli"} -: ${tautulli_chdir:="${tautulli_dir}"} -: ${tautulli_pid:="${tautulli_dir}/tautulli.pid"} -: ${tautulli_flags:=""} - -status_cmd="${name}_status" -stop_cmd="${name}_stop" - -command="${tautulli_dir}/Tautulli.py" -command_args="--daemon --pidfile ${tautulli_pid} --quiet --nolaunch ${tautulli_flags}" - -# Ensure user is root when running this script. -if [ `id -u` != "0" ]; then - echo "Oops, you should be root before running this!" - exit 1 -fi - -verify_tautulli_pid() { - # Make sure the pid corresponds to the Tautulli process. - if [ -f ${tautulli_pid} ]; then - pid=`cat ${tautulli_pid} 2>/dev/null` - ps -p ${pid} | grep -q "python ${tautulli_dir}/Tautulli.py" - return $? - else - return 0 - fi -} - -# Try to stop Tautulli cleanly by sending SIGTERM -tautulli_stop() { - echo "Stopping $name." - verify_tautulli_pid - if [ -n "${pid}" ]; then - kill ${pid} - wait_for_pids ${pid} - echo "Stopped." - fi -} - -tautulli_status() { - verify_tautulli_pid - if [ -n "${pid}" ]; then - echo "$name is running as ${pid}." - else - echo "$name is not running." - fi -} - -run_rc_command "$1" diff --git a/init-scripts/init.solaris11 b/init-scripts/init.solaris11 deleted file mode 100755 index ac7f523e..00000000 --- a/init-scripts/init.solaris11 +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/init-scripts/init.ubuntu b/init-scripts/init.ubuntu deleted file mode 100755 index b6d2345e..00000000 --- a/init-scripts/init.ubuntu +++ /dev/null @@ -1,209 +0,0 @@ -#!/bin/sh -# -## Don't edit this file -## Edit user configuation in /etc/default/tautulli to change -## -## Make sure init script is executable -## sudo chmod +x /path/to/init.ubuntu -## -## Install the init script -## sudo ln -s /path/to/init.ubuntu /etc/init.d/tautulli -## -## Create the tautulli daemon user: -## sudo adduser --system --no-create-home tautulli -## -## Make sure /opt/Tautulli is owned by the tautulli user -## sudo chown tautulli:nogroup -R /opt/Tautulli -## -## Touch the default file to stop the warning message when starting -## sudo touch /etc/default/tautulli -## -## To start Tautulli automatically -## sudo update-rc.d tautulli defaults -## -## To start/stop/restart Tautulli -## sudo service tautulli start -## sudo service tautulli stop -## sudo service tautulli restart -## -## TAUTULLI_USER= #$RUN_AS, username to run Tautulli under, the default is tautulli -## TAUTULLI_HOME= #$APP_PATH, the location of Tautulli.py, the default is /opt/Tautulli -## TAUTULLI_DATA= #$DATA_DIR, the location of plexpy.db, cache, logs, the default is /opt/Tautulli -## TAUTULLI_PIDFILE= #$PID_FILE, the location of tautulli.pid, the default is /var/run/tautulli/tautulli.pid -## PYTHON_BIN= #$DAEMON, the location of the python binary, the default is /usr/bin/python -## TAUTULLI_OPTS= #$EXTRA_DAEMON_OPTS, extra cli option for Tautulli, i.e. " --config=/home/Tautulli/config.ini" -## SSD_OPTS= #$EXTRA_SSD_OPTS, extra start-stop-daemon option like " --group=users" -## TAUTULLI_PORT= #$PORT_OPTS, hardcoded port for the webserver, overrides value in config.ini -## -## EXAMPLE if want to run as different user -## add TAUTULLI_USER=username to /etc/default/tautulli -## otherwise default tautulli is used -# -### BEGIN INIT INFO -# Provides: tautulli -# Required-Start: $local_fs $network $remote_fs -# Required-Stop: $local_fs $network $remote_fs -# Should-Start: $NetworkManager -# Should-Stop: $NetworkManager -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: starts instance of Tautulli -# Description: starts instance of Tautulli using start-stop-daemon -### END INIT INFO - -# Script name -NAME=tautulli - -# App name -DESC=Tautulli - -SETTINGS_LOADED=FALSE - -. /lib/lsb/init-functions - -# Source Tautulli configuration -if [ -f /etc/default/tautulli ]; then - SETTINGS=/etc/default/tautulli -else - log_warning_msg "/etc/default/tautulli not found using default settings."; -fi - -check_retval() { - if [ $? -eq 0 ]; then - log_end_msg 0 - return 0 - else - log_end_msg 1 - exit 1 - fi -} - -load_settings() { - if [ $SETTINGS_LOADED != "TRUE" ]; then - . $SETTINGS - - ## The defaults - # Run as username - RUN_AS=${TAUTULLI_USER-tautulli} - - # Path to app TAUTULLI_HOME=path_to_app_Tautulli.py - APP_PATH=${TAUTULLI_HOME-/opt/Tautulli} - - # Data directory where plexpy.db, cache and logs are stored - DATA_DIR=${TAUTULLI_DATA-/opt/Tautulli} - - # Path to store PID file - PID_FILE=${TAUTULLI_PIDFILE-/var/run/tautulli/tautulli.pid} - - # Path to python bin - DAEMON=${PYTHON_BIN-/usr/bin/python} - - # Extra daemon option like: TAUTULLI_OPTS=" --config=/home/Tautulli/config.ini" - EXTRA_DAEMON_OPTS=${TAUTULLI_OPTS-} - - # Extra start-stop-daemon option like START_OPTS=" --group=users" - EXTRA_SSD_OPTS=${SSD_OPTS-} - - # Hardcoded port to run on, overrides config.ini settings - [ -n "$TAUTULLI_PORT" ] && { - PORT_OPTS=" --port=${TAUTULLI_PORT} " - } - - DAEMON_OPTS=" Tautulli.py --quiet --daemon --nolaunch --pidfile=${PID_FILE} --datadir=${DATA_DIR} ${PORT_OPTS}${EXTRA_DAEMON_OPTS}" - - SETTINGS_LOADED=TRUE - fi - - [ -x $DAEMON ] || { - log_warning_msg "$DESC: Can't execute daemon, aborting. See $DAEMON"; - return 1;} - - return 0 -} - -load_settings || exit 0 - -is_running () { - # returns 1 when running, else 0. - if [ -e $PID_FILE ]; then - PID=`cat $PID_FILE` - - RET=$? - [ $RET -gt 1 ] && exit 1 || return $RET - else - return 1 - fi -} - -handle_pid () { - PID_PATH=`dirname $PID_FILE` - [ -d $PID_PATH ] || mkdir -p $PID_PATH && chown -R $RUN_AS $PID_PATH > /dev/null || { - log_warning_msg "$DESC: Could not create $PID_FILE, See $SETTINGS, aborting."; - return 1;} - - if [ -e $PID_FILE ]; then - PID=`cat $PID_FILE` - if ! kill -0 $PID > /dev/null 2>&1; then - log_warning_msg "Removing stale $PID_FILE" - rm $PID_FILE - fi - fi -} - -handle_datadir () { - [ -d $DATA_DIR ] || mkdir -p $DATA_DIR && chown -R $RUN_AS $DATA_DIR > /dev/null || { - log_warning_msg "$DESC: Could not create $DATA_DIR, See $SETTINGS, aborting."; - return 1;} -} - -handle_updates () { - chown -R $RUN_AS $APP_PATH > /dev/null || { - log_warning_msg "$DESC: $APP_PATH not writable by $RUN_AS for web-updates"; - return 0; } -} - -start_tautulli () { - handle_pid - handle_datadir - handle_updates - if ! is_running; then - log_daemon_msg "Starting $DESC" - start-stop-daemon -o -d $APP_PATH -c $RUN_AS --start $EXTRA_SSD_OPTS --pidfile $PID_FILE --exec $DAEMON -- $DAEMON_OPTS - check_retval - else - log_success_msg "$DESC: already running (pid $PID)" - fi -} - -stop_tautulli () { - if is_running; then - log_daemon_msg "Stopping $DESC" - start-stop-daemon -o --stop --pidfile $PID_FILE --retry 15 - check_retval - else - log_success_msg "$DESC: not running" - fi -} - -case "$1" in - start) - start_tautulli - ;; - stop) - stop_tautulli - ;; - restart|force-reload) - stop_tautulli - start_tautulli - ;; - status) - status_of_proc -p "$PID_FILE" "$DAEMON" "$DESC" - ;; - *) - N=/etc/init.d/$NAME - echo "Usage: $N {start|stop|restart|force-reload|status}" >&2 - exit 1 - ;; -esac - -exit 0 diff --git a/init-scripts/init.upstart b/init-scripts/init.upstart deleted file mode 100755 index 7713b143..00000000 --- a/init-scripts/init.upstart +++ /dev/null @@ -1,18 +0,0 @@ -# tautulli -# -# This is a session/user job. Install this file into /usr/share/upstart/sessions -# if Tautulli is installed system wide, and into $XDG_CONFIG_HOME/upstart if -# Tautulli is installed per user. Change the executable path appropiately. - -start on desktop-start -stop on desktop-end - -env CONFIG=""$XDG_CONFIG_HOME"/Tautulli" -env DATA=""$XDG_DATA_HOME"/Tautulli" - -pre-start script - [ -d "$CONFIG" ] || mkdir -p "$CONFIG" - [ -d "$DATA" ] || mkdir -p "$DATA" -end script - -exec Tautulli.py --nolaunch --config "$CONFIG"/config.ini --datadir "$DATA" From ab36041fefe45607d953e5001f2fd6783e5f7aaf Mon Sep 17 00:00:00 2001 From: Landon Abney Date: Sat, 28 Mar 2020 17:01:23 -0700 Subject: [PATCH 3/3] Add python to systemd script Skip the extra process calls trying to figure out what to run Tautulli with, as well as give an example on how to change the executable in the init script. --- init-scripts/init.systemd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init-scripts/init.systemd b/init-scripts/init.systemd index 22b97810..99adf3ad 100644 --- a/init-scripts/init.systemd +++ b/init-scripts/init.systemd @@ -50,7 +50,7 @@ Wants=network-online.target After=network-online.target [Service] -ExecStart=/opt/Tautulli/Tautulli.py --config /opt/Tautulli/config.ini --datadir /opt/Tautulli --quiet --daemon --nolaunch +ExecStart=python /opt/Tautulli/Tautulli.py --config /opt/Tautulli/config.ini --datadir /opt/Tautulli --quiet --daemon --nolaunch GuessMainPID=no Type=forking User=tautulli