mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-22 02:17:26 +00:00
move the custom exclusive process code from utils.py into a new python package named exclusiveprocess
This commit is contained in:
parent
09577816f8
commit
a081d04082
@ -10,8 +10,9 @@
|
|||||||
import os, os.path, shutil, glob, re, datetime, sys
|
import os, os.path, shutil, glob, re, datetime, sys
|
||||||
import dateutil.parser, dateutil.relativedelta, dateutil.tz
|
import dateutil.parser, dateutil.relativedelta, dateutil.tz
|
||||||
import rtyaml
|
import rtyaml
|
||||||
|
from exclusiveprocess import Lock
|
||||||
|
|
||||||
from utils import exclusive_process, load_environment, shell, wait_for_service, fix_boto
|
from utils import load_environment, shell, wait_for_service, fix_boto
|
||||||
|
|
||||||
rsync_ssh_options = [
|
rsync_ssh_options = [
|
||||||
"--ssh-options='-i /root/.ssh/id_rsa_miab'",
|
"--ssh-options='-i /root/.ssh/id_rsa_miab'",
|
||||||
@ -204,7 +205,10 @@ def get_target_type(config):
|
|||||||
def perform_backup(full_backup):
|
def perform_backup(full_backup):
|
||||||
env = load_environment()
|
env = load_environment()
|
||||||
|
|
||||||
exclusive_process("backup")
|
# Create an global exclusive lock so that the backup script
|
||||||
|
# cannot be run more than one.
|
||||||
|
Lock(die=True).forever()
|
||||||
|
|
||||||
config = get_backup_config(env)
|
config = get_backup_config(env)
|
||||||
backup_root = os.path.join(env["STORAGE_ROOT"], 'backup')
|
backup_root = os.path.join(env["STORAGE_ROOT"], 'backup')
|
||||||
backup_cache_dir = os.path.join(backup_root, 'cache')
|
backup_cache_dir = os.path.join(backup_root, 'cache')
|
||||||
|
@ -411,9 +411,11 @@ def provision_certificates(env, agree_to_tos_url=None, logger=None, show_extende
|
|||||||
|
|
||||||
def provision_certificates_cmdline():
|
def provision_certificates_cmdline():
|
||||||
import sys
|
import sys
|
||||||
from utils import load_environment, exclusive_process
|
from exclusiveprocess import Lock
|
||||||
|
|
||||||
exclusive_process("update_tls_certificates")
|
from utils import load_environment
|
||||||
|
|
||||||
|
Lock(die=True).forever()
|
||||||
env = load_environment()
|
env = load_environment()
|
||||||
|
|
||||||
verbose = False
|
verbose = False
|
||||||
|
@ -106,76 +106,6 @@ def sort_email_addresses(email_addresses, env):
|
|||||||
ret.extend(sorted(email_addresses)) # whatever is left
|
ret.extend(sorted(email_addresses)) # whatever is left
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def exclusive_process(name):
|
|
||||||
# Ensure that a process named `name` does not execute multiple
|
|
||||||
# times concurrently.
|
|
||||||
import os, sys, atexit
|
|
||||||
pidfile = '/var/run/mailinabox-%s.pid' % name
|
|
||||||
mypid = os.getpid()
|
|
||||||
|
|
||||||
# Attempt to get a lock on ourself so that the concurrency check
|
|
||||||
# itself is not executed in parallel.
|
|
||||||
with open(__file__, 'r+') as flock:
|
|
||||||
# Try to get a lock. This blocks until a lock is acquired. The
|
|
||||||
# lock is held until the flock file is closed at the end of the
|
|
||||||
# with block.
|
|
||||||
os.lockf(flock.fileno(), os.F_LOCK, 0)
|
|
||||||
|
|
||||||
# While we have a lock, look at the pid file. First attempt
|
|
||||||
# to write our pid to a pidfile if no file already exists there.
|
|
||||||
try:
|
|
||||||
with open(pidfile, 'x') as f:
|
|
||||||
# Successfully opened a new file. Since the file is new
|
|
||||||
# there is no concurrent process. Write our pid.
|
|
||||||
f.write(str(mypid))
|
|
||||||
atexit.register(clear_my_pid, pidfile)
|
|
||||||
return
|
|
||||||
except FileExistsError:
|
|
||||||
# The pid file already exixts, but it may contain a stale
|
|
||||||
# pid of a terminated process.
|
|
||||||
with open(pidfile, 'r+') as f:
|
|
||||||
# Read the pid in the file.
|
|
||||||
existing_pid = None
|
|
||||||
try:
|
|
||||||
existing_pid = int(f.read().strip())
|
|
||||||
except ValueError:
|
|
||||||
pass # No valid integer in the file.
|
|
||||||
|
|
||||||
# Check if the pid in it is valid.
|
|
||||||
if existing_pid:
|
|
||||||
if is_pid_valid(existing_pid):
|
|
||||||
print("Another %s is already running (pid %d)." % (name, existing_pid), file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Write our pid.
|
|
||||||
f.seek(0)
|
|
||||||
f.write(str(mypid))
|
|
||||||
f.truncate()
|
|
||||||
atexit.register(clear_my_pid, pidfile)
|
|
||||||
|
|
||||||
|
|
||||||
def clear_my_pid(pidfile):
|
|
||||||
import os
|
|
||||||
os.unlink(pidfile)
|
|
||||||
|
|
||||||
|
|
||||||
def is_pid_valid(pid):
|
|
||||||
"""Checks whether a pid is a valid process ID of a currently running process."""
|
|
||||||
# adapted from http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid
|
|
||||||
import os, errno
|
|
||||||
if pid <= 0: raise ValueError('Invalid PID.')
|
|
||||||
try:
|
|
||||||
os.kill(pid, 0)
|
|
||||||
except OSError as err:
|
|
||||||
if err.errno == errno.ESRCH: # No such process
|
|
||||||
return False
|
|
||||||
elif err.errno == errno.EPERM: # Not permitted to send signal
|
|
||||||
return True
|
|
||||||
else: # EINVAL
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def shell(method, cmd_args, env={}, capture_stderr=False, return_bytes=False, trap=False, input=None):
|
def shell(method, cmd_args, env={}, capture_stderr=False, return_bytes=False, trap=False, input=None):
|
||||||
# A safe way to execute processes.
|
# A safe way to execute processes.
|
||||||
# Some processes like apt-get require being given a sane PATH.
|
# Some processes like apt-get require being given a sane PATH.
|
||||||
|
@ -16,7 +16,7 @@ apt_install build-essential libssl-dev libffi-dev python3-dev
|
|||||||
# The first line is the packages that Josh maintains himself!
|
# The first line is the packages that Josh maintains himself!
|
||||||
# NOTE: email_validator is repeated in setup/questions.sh, so please keep the versions synced.
|
# NOTE: email_validator is repeated in setup/questions.sh, so please keep the versions synced.
|
||||||
hide_output pip3 install --upgrade \
|
hide_output pip3 install --upgrade \
|
||||||
rtyaml "email_validator>=1.0.0" "free_tls_certificates>=0.1.3" \
|
rtyaml "email_validator>=1.0.0" "free_tls_certificates>=0.1.3" "exclusiveprocess" \
|
||||||
"idna>=2.0.0" "cryptography>=1.0.2" boto psutil
|
"idna>=2.0.0" "cryptography>=1.0.2" boto psutil
|
||||||
|
|
||||||
# duplicity uses python 2 so we need to get the python 2 package of boto to have backups to S3.
|
# duplicity uses python 2 so we need to get the python 2 package of boto to have backups to S3.
|
||||||
|
Loading…
Reference in New Issue
Block a user