コード例 #1
0
ファイル: test_environment.py プロジェクト: jnrbsn/daemonocle
def test_uid_and_gid_without_permission():
    nobody = getpwnam('nobody')
    daemon = Daemon(worker=lambda: None, uid=nobody.pw_uid, gid=nobody.pw_gid)
    with pytest.raises(DaemonError) as excinfo:
        daemon.do_action('start')
    assert ('Unable to setuid or setgid '
            '([Errno 1] Operation not permitted') in str(excinfo.value)
コード例 #2
0
def test_uid_and_gid_without_permission():
    nobody = getpwnam('nobody')
    daemon = Daemon(worker=lambda: None, uid=nobody.pw_uid, gid=nobody.pw_gid)
    with pytest.raises(DaemonError) as exc_info:
        daemon.do_action('start')
    assert ('Unable to setuid or setgid '
            '([Errno 1] Operation not permitted') in str(exc_info.value)
コード例 #3
0
ファイル: test_basics.py プロジェクト: jnrbsn/daemonocle
def test_self_reload(pyscript):
    script = pyscript("""
        import os
        from daemonocle import Daemon

        daemon = Daemon(name='foo', pid_file='foo.pid', detach=False)

        def worker():
            print('here is my pid: {}'.format(os.getpid()))
            if not os.environ.get('DAEMONOCLE_RELOAD'):
                daemon.reload()

        daemon.worker = worker
        daemon.do_action('start')
    """)
    result = script.run()
    assert result.returncode == 0
    match = re.match((
        br'^Starting foo \.\.\. OK\n'
        br'here is my pid: (\d+)\n'
        br'Reloading foo \.\.\. OK\n'
        br'here is my pid: (\d+)\n'
        br'All children are gone\. Parent is exiting\.\.\.\n$'),
        result.stdout)
    assert match
    assert match.group(1) != match.group(2)
    assert result.stderr == b''

    daemon = Daemon()
    with pytest.raises(DaemonError):
        # Don't allow calling reload like this
        daemon.reload()
コード例 #4
0
def test_is_detach_necessary_ppid1(monkeypatch):
    def mock_os_getppid_1():
        return 1

    monkeypatch.setattr(os, 'getppid', mock_os_getppid_1)

    # FIXME: This isn't really how I would prefer to test this,
    # but this is a difficult thing to test.
    assert Daemon._is_detach_necessary() == Daemon._is_in_container()
コード例 #5
0
def daemonize(
    action: str,
    name: str,
    command: str | None = None,
    log_file: str | None = None,
):  # pragma: no cover
    """Executes a command as a daemon.

    Runs a COMMAND as a detached daemon assigning it a given NAME. The daemon can
    be stopped by calling daemonize stop NAME or its status checked with
    daemonize status NAME.

    If --log-file is used, a rotating log file with the STDOUT and STDERR of the
    worker subprocess will be generated. If STATUS is "debug", runs the worker
    subprocess without detaching.

    """

    def worker():

        if command is None:
            return

        if log_file:

            path = os.path.realpath(os.path.expanduser(os.path.expandvars(log_file)))
            if os.path.exists(path):
                date = datetime.now()
                suffix = date.strftime(".%Y-%m-%d_%H:%M:%S")
                move(path, path + suffix)

            os.makedirs(os.path.dirname(path), exist_ok=True)

            f = open(log_file, "w")
            sys.stdout = f
            sys.stderr = f

        subprocess.run(
            " ".join(command),
            shell=True,
            capture_output=False,
            cwd=os.getcwd(),
        )

    pid_file = f"/var/tmp/{name}.pid"

    if action == "debug":
        log_file = None
        worker()
    else:
        daemon = Daemon(
            worker=worker,
            pid_file=pid_file,
            work_dir=os.getcwd(),
        )
        daemon.do_action(action)
コード例 #6
0
ファイル: test_actions.py プロジェクト: neosun100/daemonocle
def test_default_actions():
    daemon = Daemon()
    assert daemon.list_actions() == ['start', 'stop', 'restart', 'status']
    assert daemon.get_action('start') == daemon.start
    assert daemon.get_action('stop') == daemon.stop
    assert daemon.get_action('restart') == daemon.restart
    assert daemon.get_action('status') == daemon.status
    with pytest.raises(DaemonError):
        daemon.get_action('banana')
コード例 #7
0
def test_is_detach_necessary_pid1(monkeypatch):
    def mock_os_getpid_1():
        return 1

    monkeypatch.setattr(os, 'getpid', mock_os_getpid_1)

    assert not Daemon._is_detach_necessary()
コード例 #8
0
def start(ctx, debug):
    click.secho('PKNS Server Address: ', nl=False)
    click.secho(
        f"{ctx.obj['WORKER'].ip_address}:{ctx.obj['WORKER'].port}",
        fg='green'
    )
    daemon = Daemon('PKNS Server', worker=ctx.obj['WORKER'].serve_endless,
                    detach=(not debug), pidfile=os.path.abspath(
                        os.environ['HOME']+"/.pkns/PKNS.pid"),
                    work_dir=os.path.abspath(os.environ['HOME']),
                    stdout_file=os.path.abspath(
                        os.environ['HOME'] + "/.pkns/PKNS.log"),
                    stderr_file=os.path.abspath(
                        os.environ['HOME'] + "/.pkns/PKNS_error.log"),
                    uid=os.getuid(), gid=os.getgid())
    daemon.do_action('start')
コード例 #9
0
def test_deprecated_shutdown_callback_converted_to_hook():
    def shutdown_callback(message, returncode):
        pass

    daemon = Daemon(name='foo',
                    worker=lambda: None,
                    shutdown_callback=shutdown_callback)
    assert daemon.hooks['shutdown'] is shutdown_callback
コード例 #10
0
    def get_command(self, ctx, name):
        """Get a callable command object."""

        if name not in Daemon.list_actions():
            return None

        # Assign the daemon worker as the partial of the group callback
        # with the parameters received (these are the parameters of the
        # group, not of the command).
        assert self.group_cb
        self.daemon.worker = partial(self.group_cb, **ctx.params)

        return self.commands[name]
コード例 #11
0
    def __init__(
        self,
        *args,
        callback: Union[Callable[[Any], Any], None] = None,
        log_file: Optional[str] = None,
        **kwargs,
    ):

        if "prog" not in kwargs:
            raise RuntimeError("Daemon prog not defined.")

        prog = kwargs.pop("prog")

        # Here kwargs are the parameters in the @click.group decorator.
        # pidfile is deprecated in Daemon and instead we should use pid_file, but some
        # code already use pidfile so let's support both but not at the same time.
        if "pidfile" in kwargs and "pid_file" in kwargs:
            raise RuntimeError("pid_file and pidfile are mutually exclusive.")

        base_pidfile = f"/var/tmp/{prog}.pid"
        if "pid_file" in kwargs:
            pid_file = kwargs.pop("pid_file", base_pidfile)
        elif "pidfile" in kwargs:
            pid_file = kwargs.pop("pidfile", base_pidfile)
        else:
            pid_file = base_pidfile

        daemon_params = {}
        signature = inspect.signature(Daemon).parameters
        for param in kwargs.copy():
            if param in signature and param != "name":
                daemon_params.update({param: kwargs.pop(param)})

        self.log_file = log_file

        self.daemon = Daemon(pid_file=pid_file, **daemon_params)

        # Callback is the function that @click.group decorates. What we
        # do is store it because it will become the worker for the daemon,
        # but then set it to none because we don't want the code in the group
        # function to be executed outside the daemon.
        self.group_cb = callback
        callback = None

        self.ignore_unknown_options = True
        super().__init__(*args, callback=callback, **kwargs)

        self.add_command(start)
        self.add_command(stop)
        self.add_command(restart)
        self.add_command(status)
コード例 #12
0
ファイル: test_basics.py プロジェクト: jnrbsn/daemonocle
def test_self_reload(pyscript):
    script = pyscript(
        """
        import os
        from daemonocle import Daemon

        daemon = Daemon(prog='foo', pidfile='foo.pid', detach=False)

        def worker():
            print('here is my pid: {}'.format(os.getpid()))
            if not os.environ.get('DAEMONOCLE_RELOAD'):
                daemon.reload()

        daemon.worker = worker
        daemon.do_action('start')
    """
    )
    result = script.run()
    assert result.returncode == 0
    match = re.match(
        (
            br"^Starting foo \.\.\. OK\n"
            br"here is my pid: (\d+)\n"
            br"Reloading foo \.\.\. OK\n"
            br"here is my pid: (\d+)\n"
            br"All children are gone\. Parent is exiting\.\.\.\n$"
        ),
        result.stdout,
    )
    assert match
    assert match.group(1) != match.group(2)
    assert result.stderr == b""

    daemon = Daemon()
    with pytest.raises(DaemonError):
        # Don't allow calling reload like this
        daemon.reload()
コード例 #13
0
def test_bad_shutdown_hook():
    with pytest.raises(DaemonError) as exc_info:
        Daemon(name='foo', worker=lambda: None, hooks={'shutdown': 1})
    assert str(
        exc_info.value) == ('Callback for hook "shutdown" is not callable')
コード例 #14
0
ファイル: test_basics.py プロジェクト: jnrbsn/daemonocle
def test_no_worker():
    daemon = Daemon()
    with pytest.raises(DaemonError):
        daemon.do_action("start")
コード例 #15
0
def test_chrootdir_without_permission():
    daemon = Daemon(worker=lambda: None, chroot_dir=os.getcwd())
    with pytest.raises(DaemonError) as exc_info:
        daemon.do_action('start')
    assert ('Unable to change root directory '
            '([Errno 1] Operation not permitted') in str(exc_info.value)
コード例 #16
0
ファイル: app.py プロジェクト: patron-it/opencanary
def get_app_daemon(pid_file):
    # FIXME: figure out the log prefix (opencanaryd)
    return Daemon(worker=run_twisted_app, pidfile=pid_file)
コード例 #17
0
def stop(force):
    daemon = Daemon('PKNS Server', pidfile=os.path.abspath(
                        os.environ['HOME']+"/.pkns/PKNS.pid"))
    daemon.stop(force=force)
コード例 #18
0
def status(json):
    daemon = Daemon('PKNS Server', pidfile=os.path.abspath(
                        os.environ['HOME']+"/.pkns/PKNS.pid"))
    daemon.status(json=json)
コード例 #19
0
ファイル: test_environment.py プロジェクト: jnrbsn/daemonocle
def test_chrootdir_without_permission():
    daemon = Daemon(worker=lambda: None, chrootdir=os.getcwd())
    with pytest.raises(DaemonError) as excinfo:
        daemon.do_action('start')
    assert ('Unable to change root directory '
            '([Errno 1] Operation not permitted') in str(excinfo.value)
コード例 #20
0
ファイル: test_basics.py プロジェクト: jnrbsn/daemonocle
def test_no_args_or_worker():
    daemon = Daemon()
    assert daemon.name == posixpath.basename(sys.argv[0])
    with pytest.raises(DaemonError):
        daemon.do_action('start')
コード例 #21
0
def test_no_worker():
    daemon = Daemon()
    with pytest.raises(DaemonError):
        daemon.do_action('start')