Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I need to run a script as root called root.py. I need to create notifications within the script. I made a separate script specifically for the notifications called notify.py.

Here is notify.py:

import pynotify
import sys

def notify(title, message):
    n = pynotify.Notification (title,
        message,
        "notification-message-im")
    n.show()

if __name__ == '__main__':
    notify(sys.argv[1], sys.argv[2])

notify.py script works well with a user not as root:

python notify.py Title Message

But I need to call this script inside root.py, which is ran as root. It fails if I run it as root. So, I tried to for lack of better words, sign out as root by launching it as another user (I also replaced sudo with gksudo in the following):

xhost local:user
gksudo -u user notify.py Title Message

Won't work.

Any ideas?

btw: I had a similar problem with running gtk from root ran upstart scripts. Also, gvfs won't change attributes as root when as other user as sudo.

share|improve this question

4 Answers 4

sux - wrapper around su which will transfer your X credentials http://fgouget.free.fr/sux/

$ sudo apt-get install sux
share|improve this answer
    
Is there official X credential documentation? I would like to look over just sux would be adjusting. –  bambuntu Mar 18 '12 at 21:54
    
sux is a readable shell script. Install it [sudo apt-get install sux], find its location [which sux], view it [cat $(which sux)]. If you don't like it remove it [sudo apt-get purge sux] –  jippie Mar 18 '12 at 22:19
    
Ok, but I will have to try later because I can't download now. –  bambuntu Mar 21 '12 at 21:38
    
BTW you sux from unprivileged user to root and then execute the root.py script. –  jippie Mar 21 '12 at 22:28

Direct copy and paste:

You won't be able to open a server on port 80 without root privileges, this is a restriction on the OS level. So the only solution is to drop root privileges after you have opened the port.

Here is a possible solution to drop root privileges in Python: Dropping privileges in Python. This is a good solution in general, but you'll also have to add os.setgroups([]) to the function to ensure that the group membership of the root user is not retained.

I copied and cleaned up the code a little bit, and removed logging and the exception handlers so it is left up to you to handle OSError properly (it will be thrown when the process is not allowed to switch its effective UID or GID):

import os, pwd, grp

def drop_privileges(uid_name='nobody', gid_name='nogroup'):
    if os.getuid() != 0:
        # We're not root so, like, whatever dude
        return

    # Get the uid/gid from the name
    running_uid = pwd.getpwnam(uid_name).pw_uid
    running_gid = grp.getgrnam(gid_name).gr_gid

    # Remove group privileges
    os.setgroups([])

    # Try setting the new uid/gid
    os.setgid(running_gid)
    os.setuid(running_uid)

    # Ensure a very conservative umask
    old_umask = os.umask(077)

from here.

If you MUST regain root priviledges there's always policykit.

share|improve this answer
    
This sounds like process that just needs to be started once, like a server, in which you mention. Is this really something that I can apply to a process that needs to periodically act as root? Not all things in my script are necessary as root, but some are. I'm a little unsure after dropping privileges in the parts that don't need root, how I would elevate when root was needed, since now the script would not be root id. –  bambuntu Mar 18 '12 at 22:02
    
you would launch separate processes and drop privs for those. just how i would go about it. like only return when you need more privs...but I get creative about using blocking as a tool instead of a reason to use threading. –  hbdgaf Mar 18 '12 at 22:09
    
It sounds like the main process that spawns process needs to stay as root. Each process that it spawns should have appropriate privileges set. If I got that wrong, let me know. –  bambuntu Mar 20 '12 at 0:21
    
Exactly so. Doing it any other way is just silly. If something bad happens and someone gets arbitrary execution, you're basing your execution...with the ability to regain privs...on bad data. –  hbdgaf Mar 20 '12 at 0:30

This is a wild shot, please downvote it if it's wrong. Please next time, if possible, add the relevant error messages.

Maybe the root user just lacks a display to do GUI operations. Have you tried:

DISPLAY=:0 python notify.py Title Message

as root?.

share|improve this answer
    
I tried that, but it doesn't take it as in my python subprocess.call(commandArgList) I tried the script in a root shell by itself and it worked. But won't work in my upstart script. –  bambuntu Mar 21 '12 at 21:37
    
Arguably, something that needs to interact with the GUI shouldn't be a upstart script. Myself, I will make a daemon that has to inform about something send a dbus message, then I would build a client (or clients, one for KDE, one for gnome, one command line) to listen to dbus for the message and notify the user. Note that a upstart script should work even with no user logged. That way I also has better security, as client part is not running as root, and I have the ability to notify multiple users, each one running it's own client. –  Javier Rivera Mar 22 '12 at 8:27

as root, launch :

export `dbus-launch` 

and run your notify program

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.