command is run.
Requires a connection to the management API.
+
+
+.. option:: pids
+
+ Lists the PIDs of the Manager's subprocesses, separated by newlines.
+
+ .. option:: --json
+
+ Makes the output more verbose, in JSON. In addition to the subprocesses'
+ PIDs, it also prints their types and statuses.
+
+ .. option:: [proc_type]
+
+ :default: ``all``
+
+ Optional. The type of process to query. See :ref:`Subprocess types
+ <manager-client-subprocess-types>` for more info.
+
+
+.. option:: debug
+
+ Executes a GDB-compatible debugger and attaches it to the Manager's
+ subprocesses. By default, the debugger is ``gdb`` and the subprocesses are
+ only the ``kresd`` workers.
+
+ .. warning::
+
+ The ``debug`` command is a utility for Knot Resolver developers and is
+ not intended to be used by end-users. Running this command **will** make
+ your resolver unresponsive.
+
+ .. note::
+
+ Modern kernels will prevent debuggers from tracing processes that are
+ not their descendants, which is exactly the scenario that happens with
+ ``kresctl debug``. There are three ways to work around this, listed in
+ the order in which they are preferred in terms of security:
+
+ 1. Grant the debugger the ``cap_sys_ptrace`` capability
+ (**recommended**)
+
+ * For ``gdb``, this may be achieved by using the ``setcap``
+ command like so:
+
+ .. code-block:: bash
+
+ sudo setcap cap_sys_ptrace=eip /usr/bin/gdb
+
+ 2. Run the debugger as root
+
+ * You may use the ``--sudo`` option to achieve this
+
+ 3. Set ``/proc/sys/kernel/yama/ptrace_scope`` to ``0``
+
+ * This will allow **all** programs in your current session to
+ trace each other. Handle with care!
+
+ .. note::
+
+ This command will only work if executed on the same machine where Knot
+ Resolver is running. Remote debugging is currently not supported.
+
+ .. option:: [proc_type]
+
+ :default: ``kresd``
+
+ Optional. The type of process to debug. See :ref:`Subprocess types
+ <manager-client-subprocess-types>` for more info.
+
+ .. option:: --sudo
+
+ Run the debugger with sudo.
+
+ .. option:: --gdb <command>
+
+ Use a custom GDB executable. This may be a command on ``PATH``, or an
+ absolute path to an executable.
+
+
+.. _manager-client-subprocess-types:
+
+Subprocess types
+----------------
+
+Some of ``kresctl``'s commands (like :option:`pids` and :option:`debug`) take a subprocess
+type value determining which subprocesses will be affected by them. The possible
+values are as follows:
+
+* ``kresd`` -- the worker daemons
+* ``gc`` -- the cache garbage collector
+* ``all`` -- all of the Manager's subprocesses
) -> Tuple[argparse.ArgumentParser, "Type[Command]"]:
debug = subparser.add_parser(
"debug",
- help="Run GDB on the manager's subprocesses - runs with sudo by default to avoid ptrace_scope issues",
+ help="Run GDB on the manager's subprocesses",
)
debug.add_argument(
"proc_type",
default="kresd",
)
debug.add_argument(
- "--no-sudo",
+ "--sudo",
dest="sudo",
- help="Do not run GDB with sudo (may not work if your ptrace_scope is 1 or higher)",
- action="store_false",
+ help="Run GDB with sudo",
+ action="store_true",
)
debug.add_argument(
"--gdb",
- help="GDB command (may be a command on PATH, or an absolute path)",
+ help="Custom GDB executable (may be a command on PATH, or an absolute path)",
type=str,
default=None,
)
class PidsCommand(Command):
def __init__(self, namespace: argparse.Namespace) -> None:
self.proc_type: Optional[str] = namespace.proc_type
- self.verbose: int = namespace.verbose
+ self.json: int = namespace.json
super().__init__(namespace)
def register_args_subparser(
subparser: "argparse._SubParsersAction[argparse.ArgumentParser]",
) -> Tuple[argparse.ArgumentParser, "Type[Command]"]:
- pids = subparser.add_parser("pids", help="list the PIDs of kresd manager subprocesses")
+ pids = subparser.add_parser("pids", help="List the PIDs of the Manager's subprocesses")
pids.add_argument(
"proc_type",
help="Optional, the type of process to query. May be 'kresd', 'gc', or 'all' (default).",
default="all",
)
pids.add_argument(
- "-v",
- "--verbose",
- help="Optional, makes the output more verbose, in a machine-readable format.",
- action="count",
- default=0,
+ "--json",
+ help="Optional, makes the output more verbose, in JSON.",
+ action="store_true",
+ default=False,
)
return pids, PidsCommand
if response.status == 200:
processes = json.loads(response.body)
if isinstance(processes, PROCESSES_TYPE):
- if self.verbose < 1:
- for p in processes:
- print(p["pid"])
+ if self.json:
+ print(json.dumps(processes, indent=2))
else:
for p in processes:
- print(p)
+ print(p["pid"])
else:
print(