运行os.system,就好像python不是用sudo执行的一样

运行os.system,就好像python不是用sudo执行的一样,python,python-3.x,os.system,notify-send,Python,Python 3.x,Os.system,Notify Send,当我运行下面的命令时,一切正常。没有错误,我收到一个系统通知,说你好: $ python3 >>> import os >>> os.system("notify-send Hello") 0 但是,当我这样做时: $ sudo python3 >>> import os >>> os.system("notify-send Hello") 脚本卡住了,什么也没发生 然后我试着这样做: $ sudo python3 &g

当我运行下面的命令时,一切正常。没有错误,我收到一个系统通知,说你好:

$ python3
>>> import os
>>> os.system("notify-send Hello")
0
但是,当我这样做时:

$ sudo python3
>>> import os
>>> os.system("notify-send Hello")
脚本卡住了,什么也没发生

然后我试着这样做:

$ sudo python3
>>> import os
>>> os.seteuid(1000)
>>> os.system("notify-send Hello")
1000是我的普通非root用户帐户 但是,脚本仍然被卡住,什么也没发生

我也试过:

$ sudo python3
>>> import os
>>> os.system("su my-user-name -c 'notify-send Hello'")
这是:

$ sudo python3
>>> import os
>>> os.seteuid(1000)
>>> os.system("su my-user-name -c 'notify-send Hello'")
他们都有相同的问题


我不是在寻找另一种创建通知的方法。我对子流程或notify2之类的东西不感兴趣,它们会在我的系统上造成一系列全新的问题。哦,请不要告诉我不要使用sudo。我有自己的理由。

我通过反复试验发现的实现细节是notify send需要XDG_RUNTIME_DIR环境变量才能工作-至少在以下版本中:

$ dpkg -l | grep libnotify
ii  libnotify-bin                              0.7.7-3                                      amd64        sends desktop notifications to a notification daemon (Utilities)
ii  libnotify4:amd64                           0.7.7-3                                      amd64        sends desktop notifications to a notification daemon
我首先通过使用env-I notify send hello确定它需要某种类型的环境变量,它不产生任何通知

然后,我用修改后的

如何获取该环境变量取决于您,但您需要以适当的用户身份运行notify send并设置该变量

下面是一个python脚本示例,由于os.system的安全问题,我拒绝使用它:

import os
import pwd
import subprocess
import sys


def main():
    if len(sys.argv) != 2:
        raise SystemExit(f'usage `{sys.argv[0]} USER`')
    if os.getuid() != 0:
        raise SystemExit('expected to run as root')

    # find the `gnome-session` executable, we'll use that to grab
    # XDG_RUNTIME_DIR
    cmd = ('pgrep', '-u', sys.argv[1], 'gnome-session')
    pid = int(subprocess.check_output(cmd))

    # read that process's environment
    with open(f'/proc/{pid}/environ') as f:
        for line in f.read().split('\0'):
            if line.startswith('XDG_RUNTIME_DIR='):
                _, _, xdg_runtime_dir = line.partition('=')
                break
        else:
            raise SystemExit('Could not find XDG_RUNTIME_DIR')

    # run the notify send as the right user
    uid = pwd.getpwnam(sys.argv[1]).pw_uid
    os.seteuid(uid)
    os.environ['XDG_RUNTIME_DIR'] = xdg_runtime_dir
    os.execvp('notify-send', ('notify-send', 'ohai'))


if __name__ == '__main__':
    exit(main())
免责声明:这个脚本正在做一些我不一定会在生产代码中建议的非常粗糙的事情。值得注意的是:

发送到pgrep以查找流程 读取另一个进程的环境变量 苏多 示例用法:

$ python3 t.py
usage `t.py USER`
$ python3 t.py asottile
expected to run as root
$ sudo python3 t.py asottile
# (I get a notification for `ohai`)

子流程是启动新流程的首选方式;它给您带来了什么os.system没有的问题?它导致notify send抛出错误。什么错误?这可能是您应该询问的问题。您应该使用子流程。你为什么对它不感兴趣?@chepner,我不记得了。也许我会问另一个关于这个问题的问题。现在,我只是好奇如何使用os.system解决这个问题,或者这根本不可能。