Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
#!/usr/bin/env python
""" Hypernode searchd cron watchdog
This script checks the pid of the searchd daemon and restarts it when the service is not running
It works for both Magento 1 and Magento 2 and for both live and staging.
To run it, add it to the crontab of your hypernode.
For Magento 1:
* * * * * flock -n ~/.searchd_live /data/web/ --environment live --version 1 (live)
* * * * * flock -n ~/.searchd_staging /data/web/ --environment staging --version 1 (staging)
For Magento 2:
* * * * * flock -n ~/.searchd_live /data/web/ --environment live --version 2 (live)
* * * * * flock -n ~/.searchd_staging /data/web/ --environment staging --version 2 (staging)
July 12 2017 - Flip Hes <>
import argparse
import errno
import logging
import os
import sys
import subprocess
logger = logging.getLogger('searchd-watchdog')
"staging": {
1: {
"config": "/data/web/staging/var/sphinx/sphinx.conf",
"pid": "/data/web/staging/var/sphinx/"
2: {
"config": "/data/web/magento2_staging/var/sphinx/sphinx.conf",
"pid": "/data/web/magento2_staging/var/sphinx/"
"live": {
1: {
"config": "/data/web/public/var/sphinx/sphinx.conf",
"pid": "/data/web/public/var/sphinx/"
2: {
"config": "/data/web/magento2/var/sphinx/sphinx.conf",
"pid": "/data/web/magento2/var/sphinx/"
def parse_arguments():
parser = argparse.ArgumentParser(description="Searchd watchdog")
parser.add_argument("--env", dest="environment", type=str, required=True, choices=CONFIG_DICT.keys(),
help="The environment to watch")
parser.add_argument('--version', dest='version', type=int, required=True, choices=[1, 2],
help="The magento version to use")
parser.add_argument("--log", dest="logfile", type=str, default="/data/web/sphinx.log",
help="The log file to write all output to")
arguments = parser.parse_args()
return arguments
def read_pid_file(filename):
if not filename or not os.path.isfile(filename):
return None
with open(filename) as fh:
return int(
return None
def pid_exists(pid):
"""Check whether pid exists in the current process table.
UNIX only.
if pid < 0:
return False
if pid == 0 or pid == 1:
raise ValueError('invalid PID 0 or 1')
os.kill(pid, 0)
except OSError as err:
if err.errno == errno.ESRCH:
# ESRCH == No such process
return False
elif err.errno == errno.EPERM:
# EPERM clearly means there's a process to deny access to
return True
# According to "man 2 kill" possible error values are
return True
def start_sphinx(config, logfile):
command = '/usr/bin/nohup /usr/bin/searchd --config {} 2>&1 >> {} &'.format(config, logfile)
subprocess.check_call(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=os.setpgrp)
except subprocess.CalledProcessError:
logger.error("Failed to start searchd for config {}".format(config), file=sys.stderr)
if __name__ == "__main__":
arguments = parse_arguments()
sphinx_config = CONFIG_DICT[arguments.environment][arguments.version]["config"]
sphinx_pid = CONFIG_DICT[arguments.environment][arguments.version]["pid"]
except KeyError:
logger.error('Configuration for version {} and environment {} not found!'.format(arguments.version, arguments.environment))
if not os.path.isfile(sphinx_config):
logger.error('Sphinx configuration file {} not found!'.format(sphinx_config))
pid = read_pid_file(filename=sphinx_pid)
if not pid or not pid_exists(pid=pid):'Restarting searchd daemon for {}'.format(arguments.environment))
start_sphinx(config=sphinx_config, logfile=arguments.logfile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment