You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为Python GTK4应用配置Polkit策略遇问题,求排查

问题排查与修复方案

你的核心问题是每次调用pkexec dnf都会重复要求输入密码,同时存在Polkit策略文件配置错误、RPM打包路径不匹配、应用架构设计不合理三个主要问题,以下是分步修复:


1. Polkit策略文件错误修复

你的策略文件存在三个关键问题:

  • <action>标签未闭合
  • 执行路径配置错误(直接调用Python而非应用脚本)
  • 文件名与RPM打包时的安装路径不匹配

修正后的com.prova.setup.app.policy:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
        "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
        "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<policyconfig>
    <action id="com.prova.setup.app">
        <description>Run Prova Setup as root</description>
        <message>Authenticate to run Prova Setup with root privileges</message>

        <defaults>
            <allow_any>no</allow_any>
            <allow_inactive>auth_admin_keep</allow_inactive>
            <allow_active>auth_admin_keep</allow_active>
        </defaults>
        <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/prova-setup</annotate>
        <annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
    </action> <!-- 补全闭合标签 -->
</policyconfig>

2. RPM Spec文件错误修复

你在spec文件中安装Polkit策略文件时使用了错误的文件名,导致系统无法识别该策略:

修正spec中的安装行:

install -Dm644 desktop/com.prova.setup.app.policy %{buildroot}%{_datadir}/polkit-1/actions/com.prova.setup.app.policy

同时确保你的源码包中Polkit策略文件的路径是desktop/com.prova.setup.app.policy,和安装路径对应。


3. 应用架构调整(核心:实现单次授权)

你当前的做法是每次执行DNF操作都单独调用pkexec,这会触发Polkit的重复授权检查。正确的做法是启动一个长期运行的root服务进程,通过IPC(如DBus)与GUI客户端通信,所有需要root权限的操作都通过该服务执行,这样只需要一次授权。

调整方案:

  • 拆分代码为客户端(GUI,普通用户运行)和服务端(root运行,处理DNF操作)
  • 客户端通过DBus调用服务端的方法,服务端启动时通过pkexec授权

简化版服务端示例(prova_setup/daemon.py):

import subprocess
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop

class ProvaSetupDaemon(dbus.service.Object):
    def __init__(self):
        bus_name = dbus.service.BusName('com.prova.setup.app', bus=dbus.SystemBus())
        super().__init__(bus_name, '/com/prova/setup/app')

    @dbus.service.method('com.prova.setup.app', in_signature='s', out_signature='s')
    def run_dnf_command(self, command):
        # 仅允许预定义的安全命令,避免任意命令执行
        allowed_commands = ['list installed', 'update', 'install']
        if not any(cmd in command for cmd in allowed_commands):
            return "Error: Command not allowed"
        
        try:
            result = subprocess.run(
                ['dnf'] + command.split(),
                capture_output=True, text=True, check=True
            )
            return result.stdout
        except subprocess.CalledProcessError as e:
            return e.stderr

if __name__ == '__main__':
    DBusGMainLoop(set_as_default=True)
    daemon = ProvaSetupDaemon()
    from gi.repository import GLib
    loop = GLib.MainLoop()
    loop.run()

客户端修改(调用服务端):

在你的GUI代码中,替换test()函数为:

def test():
    try:
        bus = dbus.SystemBus()
        daemon = bus.get_object('com.prova.setup.app', '/com/prova/setup/app')
        run_cmd = dbus.Interface(daemon, 'com.prova.setup.app')
        
        # 调用服务端执行DNF命令
        list_output = run_cmd.run_dnf_command('list installed')
        print([line for line in list_output.split('\n') if 'lib' in line])
        
        update_output = run_cmd.run_dnf_command('update')
        print(update_output)
    except dbus.exceptions.DBusException as e:
        # 如果服务未启动,调用pkexec启动服务
        subprocess.run(['pkexec', 'prova-setup-daemon'])
        # 重新尝试调用
        test()

更新setup.py添加服务端入口:

from setuptools import setup, find_packages

setup(
    name="prova-setup",
    version="0.1",
    packages=['prova_setup'],
    
    entry_points={
        "console_scripts": [
            "prova-setup=prova_setup.main:main",
            "prova-setup-daemon=prova_setup.daemon:main",
        ],
    },
)

4. Desktop文件修正

移除重复的Type=Application,并设置Terminal=false(GUI应用无需终端):

[Desktop Entry]
Type=Application
Version=0.1
Name=Prova di Setup.py
Comment=Una semplice ed umile descrizione
Exec=prova-setup
Icon=prova-setup.svg
Terminal=false
Categories=Utility;

验证步骤

  1. 重新构建并安装RPM包:
    rpmbuild -bb prova-setup.spec
    sudo dnf install ./rpmbuild/RPMS/noarch/prova-setup-0.1-1.fc39.noarch.rpm
    
  2. 重启Polkit服务:
    sudo systemctl restart polkit
    
  3. 启动应用,点击按钮后仅需输入一次密码,后续操作无需重复输入。

内容的提问来源于stack exchange,提问作者Herzen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 09:47:01