Becoming root within a Python script

François Pinard pinard at iro.umontreal.ca
Fri Sep 24 10:34:08 EDT 1999


wware-nospam at world.std.com (Will Ware) writes:

> : I would like, within a executing Python started as non-root, ask for
> : the root password, and then, continue executing part of the script
> : while being root, becoming the previous again after some sub-job is done.

> The os.popen().readline()[:-1] construction is pretty ugly.
> Is there a better way to do it?

Starting from your idea and working out from there, I rewrote it like this:

        import pwd, os
        self.current_user = pwd.getpwuid(os.geteuid())[0]

> [...] I did find a pretty simple version that seems to work well, at
> least on my Linux box [...]

Your solution is not fully general, but my set of problems could be bent
to fit, I believe, as I may (in my case) postpone `su-ed' parts until the
end of everything else.  So, I wrote (still untested):


class Job:

    def __init__(self, allowed):
        import pwd

        self.allowed = allowed
        self.needed_users = []
        self.current_user = pwd.getpwuid(os.geteuid())[0]

    def when(self, user):
        if user == self.current_user:
            return 1
        if user not in self.needed_users:
            self.needed_users.append(user)
        return 0

    def launch_subjobs(self):
        if self.needed_users:
            arglist = sys.argv[:]
            arglist.insert(1, '--subjob')
            argstring = join(arglist)
            for user in self.needed_users:
                execute('su %s -c "%s"' % (user, argstring))


To use it, I modified main() so it looks like:


def main(*arguments):
    global job

    if len(arguments) > 0 and arguments[0] == '--subjob':
        job = Job(0)
        del arguments[0]
    else:
        job = Job(1)

    # The rest of main() fits here...

    if job.allowed:
        job.launch_subjobs()


(To interpret what are the arguments of main(), I should say I took the
habit of writing:

if __name__ == '__main__':
    apply(main, sys.argv[1:])

as this is what I found the most convenient for interactive testing.)


To use all the above, I had to revise the application to check `job.allowed'
for the main part of the job or `job.when(USER)' for those parts requiring
a specific USER, as appropriate.  For example:

    def after_step(self):
        if job.allowed:
            execute('make')
        if job.when('root'):
            execute('make install')
            execute('cp etc/etcscreenrc /usr/local/etc/screenrc')
            execute('cat terminfo/screencap >> /etc/termcap')


This requires some care as the proper state should be restored while being
in subjobs.  But I guess it may be worked out, and is acceptably neat.

-- 
François Pinard   http://www.iro.umontreal.ca/~pinard





More information about the Python-list mailing list