blob: 5a14381fb84cd0075786832f633bb000666126d1 [file] [log] [blame]
mblighef0ac742009-11-21 01:43:07 +00001#!/usr/bin/python
2"""Service launcher that creates pidfiles and can redirect output to a file."""
mblighd3c3cf92010-02-25 18:43:40 +00003import subprocess, sys, os, optparse, signal, pwd, grp, re
mblighef0ac742009-11-21 01:43:07 +00004
5
6def stop_service(pidfile):
mblighd3c3cf92010-02-25 18:43:40 +00007 """
8 Stop a service using a pidfile.
9
10 Read the first line of a file for an integer that should refer to a pid,
11 send a SIGTERM to that pid #.
mblighef0ac742009-11-21 01:43:07 +000012 @param pidfile: file to read for the process id number
13 """
14 pidfh = open(pidfile)
15 pid = int(pidfh.readline())
16 os.kill(pid, signal.SIGTERM)
17
18
mblighd3c3cf92010-02-25 18:43:40 +000019def start_service(cmd, pidfile, logfile=os.devnull, chdir=None):
mblighef0ac742009-11-21 01:43:07 +000020 """
mblighd3c3cf92010-02-25 18:43:40 +000021 Start cmd in the background and write the pid to pidfile.
22
23 @param cmd: command to run with arguments
24 @param pidfile: pidfile to write the pid to
25 @param logfile: file to write stderr/stdout to
26 @param chdir: Directory to change to before starting the application
27 """
mblighef0ac742009-11-21 01:43:07 +000028 logfh = open(logfile, 'a')
29 pidfh = open(pidfile, 'w')
mblighef0ac742009-11-21 01:43:07 +000030 proc = subprocess.Popen(cmd, stdout=logfh, stderr=logfh, cwd=chdir)
31 pidfh.write(str(proc.pid))
32 pidfh.close()
33
34
mblighd3c3cf92010-02-25 18:43:40 +000035def get_user_name_id(user):
36 """
37 Get the user id # and name.
38
39 @param user: integer or string containing either the uid #
40 or a string username
41
42 @returns a tuple of the user name, user id
43 """
44 if re.match('\d+', str(user)):
45 pass_info = pwd.getpwuid(user)
46 else:
47 pass_info = pwd.getpwnam(user)
48
49 return pass_info[0], pass_info[2]
50
51
52def get_group_name_id(group):
53 """
54 Get the group id # and name
55
56 @param group: integer or string containing either the uid #
57 or a string username
58
59 @returns a tuple of group name, group id
60 """
61 if re.match('\d+', str(group)):
62 group_info = grp.getgrgid(group)
63 else:
64 group_info = grp.getgrnam(group)
65
66 return group_info[0], group_info[2]
67
68
69def set_group_user(group=None, user=None):
70 """
71 Set the group and user id if gid or uid is defined.
72
73 @param group: Change the group id the program is run under
74 @param user: Change the user id the program is run under
75 """
76 if group:
77 _, gid = get_group_name_id(group)
78 os.setgid(gid)
79 os.setegid(gid)
80
81 if user:
82 username, uid = get_user_name_id(user)
83 # Set environment for programs that use those to find running user
84 for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
85 os.environ[name] = username
86 os.setuid(uid)
87 os.seteuid(uid)
88
89
mblighef0ac742009-11-21 01:43:07 +000090def main():
91 parser = optparse.OptionParser()
92 parser.allow_interspersed_args = False
93 parser.add_option('-l', '--logfile', action='store',
94 default=None,
95 help='File to redirect stdout to')
96 parser.add_option('-c', '--chdir', action='store',
97 default=None,
98 help='Change to dir before starting the process')
99 parser.add_option('-s', '--start-service', action='store_true',
100 default=False,
101 help='Start service')
102 parser.add_option('-k', '--stop-service', action='store_true',
103 default=False,
104 help='Stop service')
105 parser.add_option('-p', '--pidfile', action='store',
106 default=None,
107 help='Pid file location (Required)')
mblighda98c0e2009-12-02 19:01:40 +0000108 parser.add_option('-u', '--chuid', action='store',
109 default=None,
110 help='UID to run process as')
mblighd3c3cf92010-02-25 18:43:40 +0000111 parser.add_option('-g', '--chgid', action='store',
112 default=None,
113 help='GID to run process as')
mblighda98c0e2009-12-02 19:01:40 +0000114
115
mblighef0ac742009-11-21 01:43:07 +0000116
117 options, args = parser.parse_args()
118
119 if not options.pidfile:
120 print 'A pidfile must always be supplied'
121 parser.print_help()
122 sys.exit(1)
123
mbligh18beb372010-03-03 22:28:02 +0000124 set_group_user(group=options.chgid, user=options.chuid)
mblighef0ac742009-11-21 01:43:07 +0000125 if options.start_service:
mblighd3c3cf92010-02-25 18:43:40 +0000126 start_service(args, options.pidfile, options.logfile, options.chdir)
mblighef0ac742009-11-21 01:43:07 +0000127 elif options.stop_service:
128 stop_service(options.pidfile)
129 else:
130 print 'Nothing to do, you must specify to start or stop a service'
131 parser.print_help()
132
133
134if __name__ == '__main__':
135 main()