\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7 \8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh \00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€ \00 $\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95 59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9 C/// File Manager

File Manager

Path: /opt/cloudlinux/venv/lib64/python3.11/site-packages/clwizard/

Viewing File: utils.py

# coding=utf-8
#
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENCE.TXT
#
import logging
import os
import subprocess
from contextlib import contextmanager
from typing import Iterable  # NOQA

import psutil

from .constants import CRASH_LOG_PATH
from .exceptions import PackageMissingError


@contextmanager
def atomic_write(filepath, fsync=True):
    """ Writeable file object that atomically updates a file (using a temporary file).

    :param filepath: the file path to be opened
    :param fsync: whether to force write the file to disk
    """

    tmppath = filepath + '.tmp'
    try:
        with open(tmppath, 'w', encoding='utf-8') as f:
            yield f
            if fsync:
                f.flush()
                os.fsync(f.fileno())
        os.rename(tmppath, filepath)
    finally:
        try:
            os.remove(tmppath)
        except (IOError, OSError):
            pass


def is_background_process_running(worker_pid):
    """
    Detects if the recorded background-install worker is still running.

    Only the worker PID recorded in the (root-only, flock-protected) wizard
    config is consulted, and only when that PID is BOTH alive AND still presents
    a genuine wizard-worker cmdline. This prevents an unrelated local process
    with a forged argv from being mistaken for the worker, and treats a dead or
    PID-reused entry as "not running".
    """

    def _is_wizard_cmdline(cmdline):
        # type: (Iterable[str]) -> bool
        return (
            {'/usr/sbin/cloudlinux-wizard', 'install', '--no-async'} <= set(cmdline)
            or {'/sbin/cloudlinux-wizard', 'install', '--no-async'} <= set(cmdline)
        )

    if worker_pid is None:
        return False
    try:
        cmdline = list(psutil.Process(worker_pid).cmdline())
    except psutil.NoSuchProcess:
        return False
    return _is_wizard_cmdline(cmdline)


def run_background(cmd):
    log_crash = open(CRASH_LOG_PATH, 'w', encoding='utf-8')  # pylint: disable=consider-using-with
    return subprocess.Popen(
        cmd,
        stdin=subprocess.DEVNULL,
        stdout=log_crash,
        stderr=log_crash
    )


def installed_interpreters_list(interpreter):
    try:
        from clselect.clselectctl import interpreter_versions_short_summary  # pylint: disable=import-outside-toplevel
    except ImportError as e:
        raise PackageMissingError('lvemanager') from e
    return interpreter_versions_short_summary(interpreter)


def convert_package_version(version, version_size):
    """
    Format version string
    e.g:
    3.6.0 -> 3.6 if version size = 2
    9.11.3 -> 9 if version size = 1
    :param version given version to convert
    :param version_size expected size of result version string
    """
    return '.'.join(version.split('.')[:version_size])


def setup_logger(logger_name, log_file):
    """
    Logger setup for all modules
    :return:
    """
    app_logger = logging.getLogger(logger_name)
    app_logger.setLevel(logging.INFO)
    try:
        fh = logging.FileHandler(log_file)
    except IOError:
        pass
    else:
        fh.formatter = logging.Formatter(
            '[%(levelname)s | %(asctime)s]: %(message)s')
        app_logger.addHandler(fh)
    return app_logger