1 # Unix SMB/CIFS implementation.
2 # List processes (to aid debugging on systems without setproctitle)
3 # Copyright (C) 2010-2011 Jelmer Vernooij <jelmer@samba.org>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 # Testbed for loadparm.c/params.c
20 # This module simply loads a specified configuration file and
21 # if successful, dumps it's contents to stdout. Note that the
22 # operation is performed with DEBUGLEVEL at 3.
24 # Useful for a quick 'syntax check' of a configuration file.
28 import samba.getopt as options
29 from samba.netcmd import Command, CommandError, Option
30 from samba.messaging import Messaging
33 class cmd_processes(Command):
34 """List processes (to aid debugging on systems without setproctitle)."""
36 synopsis = "%prog [options]"
38 takes_optiongroups = {
39 "sambaopts": options.SambaOptions,
40 "versionopts": options.VersionOptions
44 Option("--name", type=str,
45 help="Return only processes associated with one particular name"),
46 Option("--pid", type=int,
47 help="Return only names assoicated with one particular PID"),
53 # Get details of the samba services currently registered in irpc
54 # The prefork process model registers names in the form:
55 # prefork-master-<service> and prefork-worker-<service>-<instance>
57 # To allow this routine to identify pre-fork master and worker process
59 # returns a tuple (filtered, masters, workers)
61 # filtered - is a list of services with the prefork-* removed
62 # masters - dictionary keyed on service name of prefork master processes
63 # workers - dictionary keyed on service name containing an ordered list
64 # of worker processes.
65 def get_service_data(self, msg_ctx):
66 services = msg_ctx.irpc_all_servers()
70 for service in services:
71 for id in service.ids:
72 if service.name.startswith("prefork-master"):
73 ns = service.name.split("-")
74 name = ns[2] + "_server"
75 masters[name] = service.ids[0].pid
76 elif service.name.startswith("prefork-worker"):
77 ns = service.name.split("-")
78 name = ns[2] + "_server"
80 pid = service.ids[0].pid
81 if name not in workers:
83 workers[name][instance] = (instance, pid)
85 filtered.append(service)
86 return (filtered, masters, workers)
88 def run(self, sambaopts, versionopts, section_name=None,
91 lp = sambaopts.get_loadparm()
92 logger = self.get_logger("processes")
98 ids = msg_ctx.irpc_servers_byname(name)
102 for server_id in ids:
103 self.outf.write("%d\n" % server_id.pid)
104 elif pid is not None:
105 names = msg_ctx.irpc_all_servers()
107 for server_id in name.ids:
108 if server_id.pid == int(pid):
109 self.outf.write("%s\n" % name.name)
111 seen = {} # Service entries already printed, service names can
112 # be registered multiple times against a process
113 # but we should only display them once.
114 prefork = {} # Services running in the prefork process model
115 # want to ensure that the master process and workers
116 # are grouped to together.
117 (services, masters, workers) = self.get_service_data(msg_ctx)
118 self.outf.write(" Service: PID\n")
119 self.outf.write("--------------------------------------\n")
121 for service in sorted(services, key=lambda x: x.name):
122 if service.name in masters:
123 # If this service is running in a pre-forked process we
124 # want to print the master process followed by all the
126 pid = masters[service.name]
127 if pid not in prefork:
129 self.outf.write("%-26s %6d\n" %
131 if service.name in workers:
132 ws = workers[service.name]
134 (instance, pid) = ws[w]
135 sn = "{0}(worker {1})".format(
136 service.name, instance)
137 self.outf.write("%-26s %6d\n" % (sn, pid))
139 for server_id in service.ids:
140 if (service.name, server_id.pid) not in seen:
141 self.outf.write("%-26s %6d\n"
142 % (service.name, server_id.pid))
143 seen[(service.name, server_id.pid)] = True