-1

当我运行以下命令时,一切都按预期工作。没有错误,我收到一条系统通知说“你好”:

$ 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'")

他们都有同样的问题...

我不是在寻找另一种创建通知的方法。我对在我的系统上导致全新类别问题的subprocess事情不感兴趣。notify2哦,请不要告诉我不要使用 sudo。我有我的理由。

4

1 回答 1

3

我通过反复试验发现的实现细节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

我首先通过 using 确定它需要某种环境变量env -i notify-send hello,但没有产生任何通知。

然后我用这个脚本的修改版本一分为二

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

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

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())

免责声明:这个脚本正在做一些我不一定会在生产代码中建议的非常hacky的事情。尤其:

  • 向 pgrep 寻找进程
  • 读取另一个进程的环境变量
  • sudo

示例用法:

$ 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`)
于 2019-03-03T21:27:51.330 回答