mirror of
https://github.com/morpheus65535/bazarr.git
synced 2025-04-24 06:37:16 -04:00
Refactored Shutdown, Restart and exit status codes
This commit is contained in:
parent
c4553452a5
commit
9ae684240b
11 changed files with 210 additions and 130 deletions
105
bazarr.py
105
bazarr.py
|
@ -6,10 +6,13 @@ import signal
|
|||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import atexit
|
||||
|
||||
from bazarr.app.get_args import args
|
||||
from bazarr.literals import *
|
||||
|
||||
def exit_program(status_code):
|
||||
print(f'Bazarr exited with status code {status_code}.')
|
||||
raise SystemExit(status_code)
|
||||
|
||||
def check_python_version():
|
||||
python_version = platform.python_version_tuple()
|
||||
|
@ -19,7 +22,7 @@ def check_python_version():
|
|||
if int(python_version[0]) < minimum_py3_tuple[0]:
|
||||
print("Python " + minimum_py3_str + " or greater required. "
|
||||
"Current version is " + platform.python_version() + ". Please upgrade Python.")
|
||||
sys.exit(1)
|
||||
exit_program(EXIT_PYTHON_UPGRADE_NEEDED)
|
||||
elif int(python_version[0]) == 3 and int(python_version[1]) > 11:
|
||||
print("Python version greater than 3.11.x is unsupported. Current version is " + platform.python_version() +
|
||||
". Keep in mind that even if it works, you're on your own.")
|
||||
|
@ -27,7 +30,7 @@ def check_python_version():
|
|||
(int(python_version[0]) != minimum_py3_tuple[0]):
|
||||
print("Python " + minimum_py3_str + " or greater required. "
|
||||
"Current version is " + platform.python_version() + ". Please upgrade Python.")
|
||||
sys.exit(1)
|
||||
exit_program(EXIT_PYTHON_UPGRADE_NEEDED)
|
||||
|
||||
|
||||
def get_python_path():
|
||||
|
@ -49,55 +52,77 @@ check_python_version()
|
|||
|
||||
dir_name = os.path.dirname(__file__)
|
||||
|
||||
|
||||
def end_child_process(ep):
|
||||
try:
|
||||
if os.name != 'nt':
|
||||
try:
|
||||
ep.send_signal(signal.SIGINT)
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
else:
|
||||
import win32api
|
||||
import win32con
|
||||
try:
|
||||
win32api.GenerateConsoleCtrlEvent(win32con.CTRL_C_EVENT, ep.pid)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except:
|
||||
ep.terminate()
|
||||
|
||||
|
||||
def start_bazarr():
|
||||
script = [get_python_path(), "-u", os.path.normcase(os.path.join(dir_name, 'bazarr', 'main.py'))] + sys.argv[1:]
|
||||
ep = subprocess.Popen(script, stdout=None, stderr=None, stdin=subprocess.DEVNULL)
|
||||
atexit.register(end_child_process, ep=ep)
|
||||
signal.signal(signal.SIGTERM, lambda signal_no, frame: end_child_process(ep))
|
||||
print(f"Bazarr starting child process with PID {ep.pid}...")
|
||||
return ep
|
||||
|
||||
|
||||
def terminate_child():
|
||||
print(f"Terminating child process with PID {child_process.pid}")
|
||||
child_process.terminate()
|
||||
|
||||
|
||||
def get_stop_status_code(input_file):
|
||||
try:
|
||||
with open(input_file,'r') as file:
|
||||
# read status code from file, if it exists
|
||||
line = file.readline()
|
||||
try:
|
||||
status_code = int(line)
|
||||
except (ValueError, TypeError):
|
||||
status_code = EXIT_NORMAL
|
||||
file.close()
|
||||
except:
|
||||
status_code = EXIT_NORMAL
|
||||
return status_code
|
||||
|
||||
|
||||
def check_status():
|
||||
global child_process
|
||||
if os.path.exists(stopfile):
|
||||
status_code = get_stop_status_code(stopfile)
|
||||
try:
|
||||
print(f"Deleting stop file...")
|
||||
os.remove(stopfile)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
print('Unable to delete stop file.')
|
||||
finally:
|
||||
print('Bazarr exited.')
|
||||
sys.exit(0)
|
||||
terminate_child()
|
||||
exit_program(status_code)
|
||||
|
||||
if os.path.exists(restartfile):
|
||||
try:
|
||||
print(f"Deleting restart file...")
|
||||
os.remove(restartfile)
|
||||
except Exception:
|
||||
print('Unable to delete restart file.')
|
||||
else:
|
||||
print("Bazarr is restarting...")
|
||||
start_bazarr()
|
||||
finally:
|
||||
terminate_child()
|
||||
print(f"Bazarr is restarting...")
|
||||
child_process = start_bazarr()
|
||||
|
||||
|
||||
def interrupt_handler(signum, frame):
|
||||
# catch and ignore keyboard interrupt Ctrl-C
|
||||
# the child process Server object will catch SIGINT and perform an orderly shutdown
|
||||
global interrupted
|
||||
if not interrupted:
|
||||
# ignore user hammering Ctrl-C; we heard you the first time!
|
||||
interrupted = True
|
||||
print('Handling keyboard interrupt...')
|
||||
else:
|
||||
print(f"Stop doing that! I heard you the first time!")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
restartfile = os.path.join(args.config_dir, 'bazarr.restart')
|
||||
stopfile = os.path.join(args.config_dir, 'bazarr.stop')
|
||||
interrupted = False
|
||||
signal.signal(signal.SIGINT, interrupt_handler)
|
||||
restartfile = os.path.join(args.config_dir, FILE_RESTART)
|
||||
stopfile = os.path.join(args.config_dir, FILE_STOP)
|
||||
os.environ[ENV_STOPFILE] = stopfile
|
||||
os.environ[ENV_RESTARTFILE] = restartfile
|
||||
|
||||
# Cleanup leftover files
|
||||
try:
|
||||
|
@ -111,18 +136,14 @@ if __name__ == '__main__':
|
|||
pass
|
||||
|
||||
# Initial start of main bazarr process
|
||||
print("Bazarr starting...")
|
||||
start_bazarr()
|
||||
child_process = start_bazarr()
|
||||
|
||||
# Keep the script running forever until stop is requested through term or keyboard interrupt
|
||||
# Keep the script running forever until stop is requested through term, special files or keyboard interrupt
|
||||
while True:
|
||||
check_status()
|
||||
try:
|
||||
if sys.platform.startswith('win'):
|
||||
time.sleep(5)
|
||||
else:
|
||||
os.wait()
|
||||
time.sleep(1)
|
||||
time.sleep(5)
|
||||
except (KeyboardInterrupt, SystemExit, ChildProcessError):
|
||||
print('Bazarr exited.')
|
||||
sys.exit(0)
|
||||
# this code should never be reached, if signal handling is working properly
|
||||
print(f'Bazarr exited main script file via keyboard interrupt.')
|
||||
exit_program(EXIT_INTERRUPT)
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
# coding=utf-8
|
||||
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
|
||||
from flask_restx import Resource, Namespace, fields, marshal
|
||||
|
||||
from app.config import settings
|
||||
from app.logger import empty_log
|
||||
from app.get_args import args
|
||||
|
||||
from utilities.central import get_log_file_path
|
||||
from ..utils import authenticate
|
||||
|
||||
api_ns_system_logs = Namespace('System Logs', description='List log file entries or empty log file')
|
||||
|
@ -54,7 +55,7 @@ class SystemLogs(Resource):
|
|||
include = include.casefold()
|
||||
exclude = exclude.casefold()
|
||||
|
||||
with io.open(os.path.join(args.config_dir, 'log', 'bazarr.log'), encoding='UTF-8') as file:
|
||||
with io.open(get_log_file_path(), encoding='UTF-8') as file:
|
||||
raw_lines = file.read()
|
||||
lines = raw_lines.split('|\n')
|
||||
for line in lines:
|
||||
|
|
|
@ -7,6 +7,8 @@ import logging
|
|||
import re
|
||||
|
||||
from urllib.parse import quote_plus
|
||||
from literals import EXIT_VALIDATION_ERROR
|
||||
from utilities.central import stop_bazarr
|
||||
from subliminal.cache import region
|
||||
from dynaconf import Dynaconf, Validator as OriginalValidator
|
||||
from dynaconf.loaders.yaml_loader import write
|
||||
|
@ -410,8 +412,9 @@ while failed_validator:
|
|||
settings[current_validator_details.names[0]] = current_validator_details.default
|
||||
else:
|
||||
logging.critical(f"Value for {current_validator_details.names[0]} doesn't pass validation and there's no "
|
||||
f"default value. This issue must be reported. Bazarr won't works until it's been fixed.")
|
||||
os._exit(0)
|
||||
f"default value. This issue must be reported to and fixed by the development team. "
|
||||
f"Bazarr won't work until it's been fixed.")
|
||||
stop_bazarr(EXIT_VALIDATION_ERROR)
|
||||
|
||||
|
||||
def write_config():
|
||||
|
|
|
@ -8,6 +8,7 @@ import platform
|
|||
import warnings
|
||||
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
from utilities.central import get_log_file_path
|
||||
from pytz_deprecation_shim import PytzUsageWarning
|
||||
|
||||
from .get_args import args
|
||||
|
@ -61,16 +62,19 @@ class UnwantedWaitressMessageFilter(logging.Filter):
|
|||
if settings.general.debug is True:
|
||||
# no filtering in debug mode
|
||||
return True
|
||||
|
||||
unwantedMessages = [
|
||||
"Exception while serving /api/socket.io/",
|
||||
['Session is disconnected', 'Session not found' ],
|
||||
|
||||
"Exception while serving /api/socket.io/",
|
||||
["'Session is disconnected'", "'Session not found'" ],
|
||||
|
||||
"Exception while serving /api/socket.io/",
|
||||
['"Session is disconnected"', '"Session not found"' ],
|
||||
|
||||
unwantedMessages = [
|
||||
"Exception while serving /api/socket.io/",
|
||||
['Session is disconnected', 'Session not found'],
|
||||
|
||||
"Exception while serving /api/socket.io/",
|
||||
["'Session is disconnected'", "'Session not found'"],
|
||||
|
||||
"Exception while serving /api/socket.io/",
|
||||
['"Session is disconnected"', '"Session not found"']
|
||||
"Exception when servicing %r",
|
||||
[],
|
||||
]
|
||||
|
||||
wanted = True
|
||||
|
@ -79,7 +83,7 @@ class UnwantedWaitressMessageFilter(logging.Filter):
|
|||
if record.msg == unwantedMessages[i]:
|
||||
exceptionTuple = record.exc_info
|
||||
if exceptionTuple is not None:
|
||||
if str(exceptionTuple[1]) in unwantedMessages[i+1]:
|
||||
if len(unwantedMessages[i+1]) == 0 or str(exceptionTuple[1]) in unwantedMessages[i+1]:
|
||||
wanted = False
|
||||
break
|
||||
|
||||
|
@ -112,10 +116,10 @@ def configure_logging(debug=False):
|
|||
# File Logging
|
||||
global fh
|
||||
if sys.version_info >= (3, 9):
|
||||
fh = PatchedTimedRotatingFileHandler(os.path.join(args.config_dir, 'log/bazarr.log'), when="midnight",
|
||||
fh = PatchedTimedRotatingFileHandler(get_log_file_path(), when="midnight",
|
||||
interval=1, backupCount=7, delay=True, encoding='utf-8')
|
||||
else:
|
||||
fh = TimedRotatingFileHandler(os.path.join(args.config_dir, 'log/bazarr.log'), when="midnight", interval=1,
|
||||
fh = TimedRotatingFileHandler(get_log_file_path(), when="midnight", interval=1,
|
||||
backupCount=7, delay=True, encoding='utf-8')
|
||||
f = FileHandlerFormatter('%(asctime)s|%(levelname)-8s|%(name)-32s|%(message)s|',
|
||||
'%Y-%m-%d %H:%M:%S')
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
# coding=utf-8
|
||||
|
||||
import signal
|
||||
import warnings
|
||||
import logging
|
||||
import os
|
||||
import io
|
||||
import errno
|
||||
from literals import EXIT_INTERRUPT, EXIT_NORMAL
|
||||
from utilities.central import restart_bazarr, stop_bazarr
|
||||
|
||||
from waitress.server import create_server
|
||||
from time import sleep
|
||||
|
@ -37,6 +38,7 @@ class Server:
|
|||
self.connected = False
|
||||
self.address = str(settings.general.ip)
|
||||
self.port = int(args.port) if args.port else int(settings.general.port)
|
||||
self.interrupted = False
|
||||
|
||||
while not self.connected:
|
||||
sleep(0.1)
|
||||
|
@ -62,9 +64,17 @@ class Server:
|
|||
logging.exception("BAZARR cannot start because of unhandled exception.")
|
||||
self.shutdown()
|
||||
|
||||
def interrupt_handler(self, signum, frame):
|
||||
# print('Server signal interrupt handler called with signal', signum)
|
||||
if not self.interrupted:
|
||||
# ignore user hammering Ctrl-C; we heard you the first time!
|
||||
self.interrupted = True
|
||||
self.shutdown(EXIT_INTERRUPT)
|
||||
|
||||
def start(self):
|
||||
logging.info(f'BAZARR is started and waiting for request on http://{self.server.effective_host}:'
|
||||
f'{self.server.effective_port}')
|
||||
signal.signal(signal.SIGINT, self.interrupt_handler)
|
||||
try:
|
||||
self.server.run()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
|
@ -72,31 +82,19 @@ class Server:
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
def shutdown(self):
|
||||
try:
|
||||
stop_file = io.open(os.path.join(args.config_dir, "bazarr.stop"), "w", encoding='UTF-8')
|
||||
except Exception as e:
|
||||
logging.error(f'BAZARR Cannot create stop file: {repr(e)}')
|
||||
else:
|
||||
logging.info('Bazarr is being shutdown...')
|
||||
stop_file.write(str(''))
|
||||
stop_file.close()
|
||||
close_database()
|
||||
self.server.close()
|
||||
os._exit(0)
|
||||
def close_all(self):
|
||||
print(f"Closing database...")
|
||||
close_database()
|
||||
print(f"Closing webserver...")
|
||||
self.server.close()
|
||||
|
||||
def shutdown(self, status=EXIT_NORMAL):
|
||||
self.close_all()
|
||||
stop_bazarr(status, False)
|
||||
|
||||
def restart(self):
|
||||
try:
|
||||
restart_file = io.open(os.path.join(args.config_dir, "bazarr.restart"), "w", encoding='UTF-8')
|
||||
except Exception as e:
|
||||
logging.error(f'BAZARR Cannot create restart file: {repr(e)}')
|
||||
else:
|
||||
logging.info('Bazarr is being restarted...')
|
||||
restart_file.write(str(''))
|
||||
restart_file.close()
|
||||
close_database()
|
||||
self.server.close()
|
||||
os._exit(0)
|
||||
self.close_all()
|
||||
restart_bazarr()
|
||||
|
||||
|
||||
webserver = Server()
|
||||
|
|
|
@ -9,9 +9,11 @@ from functools import wraps
|
|||
from urllib.parse import unquote
|
||||
|
||||
from constants import headers
|
||||
from literals import FILE_LOG
|
||||
from sonarr.info import url_api_sonarr
|
||||
from radarr.info import url_api_radarr
|
||||
from utilities.helper import check_credentials
|
||||
from utilities.central import get_log_file_path
|
||||
|
||||
from .config import settings, base_url
|
||||
from .database import System
|
||||
|
@ -98,9 +100,9 @@ def catch_all(path):
|
|||
|
||||
|
||||
@check_login
|
||||
@ui_bp.route('/bazarr.log')
|
||||
@ui_bp.route('/' + FILE_LOG)
|
||||
def download_log():
|
||||
return send_file(os.path.join(args.config_dir, 'log', 'bazarr.log'), max_age=0, as_attachment=True)
|
||||
return send_file(get_log_file_path(), max_age=0, as_attachment=True)
|
||||
|
||||
|
||||
@check_login
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# coding=utf-8
|
||||
|
||||
import os
|
||||
import io
|
||||
import sys
|
||||
import subprocess
|
||||
import subliminal
|
||||
|
@ -20,6 +19,9 @@ from utilities.backup import restore_from_backup
|
|||
|
||||
from app.database import init_db
|
||||
|
||||
from literals import *
|
||||
from utilities.central import make_bazarr_dir, restart_bazarr, stop_bazarr
|
||||
|
||||
# set start time global variable as epoch
|
||||
global startTime
|
||||
startTime = time.time()
|
||||
|
@ -37,20 +39,15 @@ if not os.path.exists(args.config_dir):
|
|||
os.mkdir(os.path.join(args.config_dir))
|
||||
except OSError:
|
||||
print("BAZARR The configuration directory doesn't exist and Bazarr cannot create it (permission issue?).")
|
||||
exit(2)
|
||||
stop_bazarr(EXIT_CONFIG_CREATE_ERROR)
|
||||
|
||||
if not os.path.exists(os.path.join(args.config_dir, 'config')):
|
||||
os.mkdir(os.path.join(args.config_dir, 'config'))
|
||||
if not os.path.exists(os.path.join(args.config_dir, 'db')):
|
||||
os.mkdir(os.path.join(args.config_dir, 'db'))
|
||||
if not os.path.exists(os.path.join(args.config_dir, 'log')):
|
||||
os.mkdir(os.path.join(args.config_dir, 'log'))
|
||||
if not os.path.exists(os.path.join(args.config_dir, 'cache')):
|
||||
os.mkdir(os.path.join(args.config_dir, 'cache'))
|
||||
if not os.path.exists(os.path.join(args.config_dir, 'backup')):
|
||||
os.mkdir(os.path.join(args.config_dir, 'backup'))
|
||||
if not os.path.exists(os.path.join(args.config_dir, 'restore')):
|
||||
os.mkdir(os.path.join(args.config_dir, 'restore'))
|
||||
os.environ[ENV_BAZARR_ROOT_DIR] = os.path.join(args.config_dir)
|
||||
make_bazarr_dir(DIR_BACKUP)
|
||||
make_bazarr_dir(DIR_CACHE)
|
||||
make_bazarr_dir(DIR_CONFIG)
|
||||
make_bazarr_dir(DIR_DB)
|
||||
make_bazarr_dir(DIR_LOG)
|
||||
make_bazarr_dir(DIR_RESTORE)
|
||||
|
||||
# set subliminal_patch hearing-impaired extension to use when naming subtitles
|
||||
os.environ["SZ_HI_EXTENSION"] = settings.general.hi_extension
|
||||
|
@ -99,19 +96,11 @@ if not args.no_update:
|
|||
subprocess.check_output(pip_command, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
logging.exception(f'BAZARR requirements.txt installation result: {e.stdout}')
|
||||
os._exit(1)
|
||||
os._exit(EXIT_REQUIREMENTS_ERROR)
|
||||
else:
|
||||
logging.info('BAZARR requirements installed.')
|
||||
|
||||
try:
|
||||
restart_file = io.open(os.path.join(args.config_dir, "bazarr.restart"), "w", encoding='UTF-8')
|
||||
except Exception as e:
|
||||
logging.error(f'BAZARR Cannot create restart file: {repr(e)}')
|
||||
else:
|
||||
logging.info('Bazarr is being restarted...')
|
||||
restart_file.write(str(''))
|
||||
restart_file.close()
|
||||
os._exit(0)
|
||||
restart_bazarr()
|
||||
|
||||
# change default base_url to ''
|
||||
settings.general.base_url = settings.general.base_url.rstrip('/')
|
||||
|
|
30
bazarr/literals.py
Normal file
30
bazarr/literals.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
# coding=utf-8
|
||||
|
||||
# only primitive types can be specified here
|
||||
# for other derived values, use constants.py
|
||||
|
||||
# bazarr environment variable names
|
||||
ENV_STOPFILE = 'STOPFILE'
|
||||
ENV_RESTARTFILE = 'RESTARTFILE'
|
||||
ENV_BAZARR_ROOT_DIR = 'BAZARR_ROOT'
|
||||
|
||||
# bazarr subdirectories
|
||||
DIR_BACKUP = 'backup'
|
||||
DIR_CACHE = 'cache'
|
||||
DIR_CONFIG = 'config'
|
||||
DIR_DB = 'db'
|
||||
DIR_LOG = 'log'
|
||||
DIR_RESTORE = 'restore'
|
||||
|
||||
# bazarr special files
|
||||
FILE_LOG = 'bazarr.log'
|
||||
FILE_RESTART = 'bazarr.restart'
|
||||
FILE_STOP = 'bazarr.stop'
|
||||
|
||||
# bazarr exit codes
|
||||
EXIT_NORMAL = 0
|
||||
EXIT_INTERRUPT = -100
|
||||
EXIT_VALIDATION_ERROR = -101
|
||||
EXIT_CONFIG_CREATE_ERROR = -102
|
||||
EXIT_PYTHON_UPGRADE_NEEDED = -103
|
||||
EXIT_REQUIREMENTS_ERROR = -104
|
|
@ -44,16 +44,8 @@ from app.server import webserver, app # noqa E402
|
|||
from app.announcements import get_announcements_to_file # noqa E402
|
||||
|
||||
if args.create_db_revision:
|
||||
try:
|
||||
stop_file = io.open(os.path.join(args.config_dir, "bazarr.stop"), "w", encoding='UTF-8')
|
||||
except Exception as e:
|
||||
logging.error(f'BAZARR Cannot create stop file: {repr(e)}')
|
||||
else:
|
||||
create_db_revision(app)
|
||||
logging.info('Bazarr is being shutdown...')
|
||||
stop_file.write(str(''))
|
||||
stop_file.close()
|
||||
os._exit(0)
|
||||
create_db_revision(app)
|
||||
stop_bazarr(EXIT_NORMAL)
|
||||
else:
|
||||
migrate_db(app)
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# coding=utf-8
|
||||
|
||||
import os
|
||||
import io
|
||||
import sqlite3
|
||||
import shutil
|
||||
import logging
|
||||
|
@ -12,6 +11,7 @@ from glob import glob
|
|||
|
||||
from app.get_args import args
|
||||
from app.config import settings
|
||||
from utilities.central import restart_bazarr
|
||||
|
||||
|
||||
def get_backup_path():
|
||||
|
@ -133,16 +133,7 @@ def restore_from_backup():
|
|||
logging.exception(f'Unable to delete {dest_database_path}')
|
||||
|
||||
logging.info('Backup restored successfully. Bazarr will restart.')
|
||||
|
||||
try:
|
||||
restart_file = io.open(os.path.join(args.config_dir, "bazarr.restart"), "w", encoding='UTF-8')
|
||||
except Exception as e:
|
||||
logging.error(f'BAZARR Cannot create restart file: {repr(e)}')
|
||||
else:
|
||||
logging.info('Bazarr is being restarted...')
|
||||
restart_file.write('')
|
||||
restart_file.close()
|
||||
os._exit(0)
|
||||
restart_bazarr()
|
||||
elif os.path.isfile(restore_config_path) or os.path.isfile(restore_database_path):
|
||||
logging.debug('Cannot restore a partial backup. You must have both config and database.')
|
||||
else:
|
||||
|
|
49
bazarr/utilities/central.py
Normal file
49
bazarr/utilities/central.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
# coding=utf-8
|
||||
|
||||
# only methods can be specified here that do not cause other moudules to be loaded
|
||||
# for other methods that use settings, etc., use utilities/helper.py
|
||||
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from literals import *
|
||||
|
||||
def get_bazarr_dir(sub_dir):
|
||||
path = os.path.join(os.environ[ENV_BAZARR_ROOT_DIR], sub_dir)
|
||||
return path
|
||||
|
||||
def make_bazarr_dir(sub_dir):
|
||||
path = get_bazarr_dir(sub_dir)
|
||||
if not os.path.exists(path):
|
||||
os.mkdir(path)
|
||||
|
||||
def get_log_file_path():
|
||||
path = os.path.join(get_bazarr_dir(DIR_LOG), FILE_LOG)
|
||||
return path
|
||||
|
||||
def get_stop_file_path():
|
||||
return os.environ[ENV_STOPFILE]
|
||||
|
||||
def get_restart_file_path():
|
||||
return os.environ[ENV_RESTARTFILE]
|
||||
|
||||
def stop_bazarr(status_code=EXIT_NORMAL, exit_main=True):
|
||||
try:
|
||||
with open(get_stop_file_path(),'w', encoding='UTF-8') as file:
|
||||
# write out status code for final exit
|
||||
file.write(f'{status_code}\n')
|
||||
file.close()
|
||||
except Exception as e:
|
||||
logging.error(f'BAZARR Cannot create stop file: {repr(e)}')
|
||||
logging.info('Bazarr is being shutdown...')
|
||||
if exit_main:
|
||||
raise SystemExit(status_code)
|
||||
|
||||
def restart_bazarr():
|
||||
try:
|
||||
Path(get_restart_file_path()).touch()
|
||||
except Exception as e:
|
||||
logging.error(f'BAZARR Cannot create restart file: {repr(e)}')
|
||||
logging.info('Bazarr is being restarted...')
|
||||
raise SystemExit(EXIT_NORMAL)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue