如何以及在哪里通过 macOS 基于 Python 的应用程序上的本机 GUI 最好地检索 sudo 密码 - (同时维护交互式输出流 (stdout))

2024-01-24

好的,情况是这样的:我正在使用 Python 和 wx (wxphoenix) 构建 macOS GUI 应用程序。用户可以使用 GUI(例如:script1)启动文件删除过程(包含在script2)。为了顺利运行script2需要以 sudo 权限运行。

script2将迭代一长串文件并删除它们。但我需要它与包含的 GUI 进行通信script1每轮之后script1可以更新进度条。

这是我的绝对最基本的形式当前工作设置看起来像这样:

Script1:

import io
from threading import Thread
import subprocess

import wx

# a whole lot of wx GUI stuff 

def get_password():
    """Retrieve user password via a GUI"""

    # A wx solution using wx.PasswordEntryDialog()
    # Store password in a variable

    return variable

class run_script_with_sudo(Thread):
    """Launch a script with administrator privileges"""

    def __init__(self, path_to_script, wx_pubsub_sendmessage):
        """Set variables to self"""
        self.path = path_to_script
        self.sender = wx_pubsub_sendmessage
        self.password = get_password()
        Thread.__init__(self)
        self.start()

    def run(self):
        """Run thread"""

        prepare_script = subprocess.Popen(["echo", password], stdout=subprocess.PIPE)
        prepare_script.wait()
        launch_script = subprocess.Popen(['sudo', '-S', '/usr/local/bin/python3.6', '-u', self.path], stdin=prepare_script.stdout, stdout=subprocess.PIPE)
        for line in io.TextIOWrapper(launch_script.stdout, encoding="utf-8"):
            print("Received line: ", line.rstrip())
            # Tell progressbar to add another step:
            wx.CallAfter(self.sender, "update", msg="")

Script2:

import time

# This is a test setup, just a very simple loop that produces an output.

for i in range(25):
    time.sleep(1)
    print(i)

上述设置的工作原理是script1接收的输出script2实时并对其采取行动。 (所以在给定的例子中:每一秒之后script1向进度条添加另一个步骤,直到达到 25 步)。

我想要实现什么= 不将密码存储在变量中,并使用 macOS 的本机 GUI 来检索密码。

但是当我改变时:

prepare_script = subprocess.Popen(["echo", password], stdout=subprocess.PIPE)
prepare_script.wait()
launch_script = subprocess.Popen(['sudo', '-S', '/usr/local/bin/python3.6', '-u', self.path], stdin=prepare_script.stdout, stdout=subprocess.PIPE)
for line in io.TextIOWrapper(launch_script.stdout, encoding="utf-8"):
                print("Received line: ", line.rstrip())
                # Tell progressbar to add another step:
                wx.CallAfter(self.sender, "update", msg="")

Into:

command = r"""/usr/bin/osascript -e 'do shell script "/usr/local/bin/python3.6 -u """ + self.path + """ with prompt "Sart Deletion Process " with administrator privileges'"""
command_list = shlex.split(command)

launch_script = subprocess.Popen(command_list, stdout=subprocess.PIPE)
for line in io.TextIOWrapper(launch_script.stdout, encoding="utf-8"):
    print("Received line: ", line.rstrip())
    # Tell progressbar to add another step:
    wx.CallAfter(self.sender, "update", msg="")

它停止工作,因为 osascript 显然在非交互式 shell 中运行 https://stackoverflow.com/a/49156646/4041795。这意味着script2在完全完成之前不发送任何输出,导致进度条script1拖延。

我的问题就变成了:我怎样才能确保使用 macOS 本机 GUI 来询问 sudo 密码,从而避免将其存储在变量中,同时仍然保持从交互式/实时流中的特权脚本捕获标准输出的可能性。

希望这是有道理的。

将不胜感激任何见解!


我的问题就变成了: 如何确保使用 macOS 原生 GUI 询问 sudo 密码,从而避免将其存储在 变量,同时仍然保持捕获标准输出的可能性 来自交互式/实时流中的特权脚本。

我自己找到了一个解决方案,使用命名管道 (os.mkfifo()).

这样,您可以让 2 个 python 脚本相互通信,同时其中 1 个脚本通过 osascript 以特权权限启动(这意味着:您将获得一个本机 GUI 窗口,要求用户输入 sudo 密码)。

工作溶液:

主脚本.py

import os
from pathlib import Path
import shlex
import subprocess
import sys
from threading import Thread
import time

class LaunchDeletionProcess(Thread):

    def __init__(self):

        Thread.__init__(self)

    def run(self):

        launch_command = r"""/usr/bin/osascript -e 'do shell script "/usr/local/bin/python3.6 -u /path/to/priviliged_script.py" with prompt "Sart Deletion Process " with administrator privileges'"""
        split_command = shlex.split(launch_command)

        print("Thread 1 started")
        testprogram = subprocess.Popen(split_command)
        testprogram.wait()
        print("Thread1 Finished")

class ReadStatus(Thread):

    def __init__(self):

        Thread.__init__(self)

    def run(self):

        while not os.path.exists(os.path.expanduser("~/p1")):
            time.sleep(0.1)

        print("Thread 2 started")

        self.wfPath = os.path.expanduser("~/p1")

        rp = open(self.wfPath, 'r')
        response = rp.read()

        self.try_pipe(response)

    def try_pipe(self, response):
        rp = open(self.wfPath, 'r')
        response = rp.read()
        print("Receiving response: ", response)
        rp.close()
        if response == str(self.nr_of_steps-1):
            print("Got to end")
            os.remove(os.path.expanduser("~/p1"))
        else:
            time.sleep(1)
            self.try_pipe(response)

if __name__ == "__main__":

    thread1 = LaunchDeletionProcess()
    thread2 = ReadStatus()
    thread1.start()
    thread2.start()

priviliged_script.py

import os
import time
import random

wfPath = os.path.expanduser("~/p1")

try:

    os.mkfifo(wfPath)

except OSError:

    print("error")
    pass

result = 10

nr = 0 

while nr < result:

    random_nr = random.random()

    wp = open(wfPath, 'w')
    print("writing new number: ", random_nr)
    wp.write("Number: " + str(random_nr))       
    wp.close()

    time.sleep(1)
    nr += 1

wp = open(wfPath, 'w')
wp.write("end")     
wp.close()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何以及在哪里通过 macOS 基于 Python 的应用程序上的本机 GUI 最好地检索 sudo 密码 - (同时维护交互式输出流 (stdout)) 的相关文章

随机推荐

  • 在knockout js中将循环结构转换为JSON

    我有两个网格结构 在其中一个网格结构中我多次有多个字段 而在其中一个网格结构中我一次有两个字段 我为每个网格编写 apply 方法 我的第一个网格 id 工作正常 但是当我单击第二个网格上的 应用 时 我收到此错误 Uncaught Typ
  • 在 C++ 软件中纳入共享软件限制

    我希望在共享软件的基础上实现我的软件 以便用户 给予最多 例如 30 天的试用期来试用该软件 购买时 我打算向用户提供一个随机生成的密钥 输入该密钥时 再次启用该软件 我以前从未走过这条路 所以任何建议 反馈或关于如何完成此操作的 标准 方
  • 避免重新计算 Beam Python SDK 中所有云存储文件的大小

    我正在开发一个从 Google Cloud Storage GCS 目录读取约 500 万个文件的管道 我已将其配置为在 Google Cloud Dataflow 上运行 问题是 当我启动管道时 需要几个小时 计算所有文件的大小 INFO
  • 找不到 pyinstaller 命令

    我在 VirtualBox 上使用 Ubuntu 我该如何添加pyinstaller to the PATH 问题是当我说 pyinstaller file py 它说找不到 pyinstaller 命令 它说它安装正确 根据其他帖子 我认
  • 删除 X-Powered-By

    如何删除 PHP 中的 X Powered By 标头 我在 Apache 服务器上 使用 php 5 21 我无法在 php 中使用 header remove 函数 因为 5 21 不支持它 我使用了 Header unset X Po
  • 检测点是否在 SVG 路径内

    我正在尝试检测给定点是否位于 Objective C 中的闭合 SVG 路径内 我不知道如何做数学 我有一个路径的坐标 我想确定一个随机点是在路径内部还是外部 这是路径坐标的示例 M673 460 c2 0 4 1 5 2 1 1 2 2
  • Objective-C 中的全局变量 - extern 和 .m 文件顶部声明的差异

    我知道你可以使用 extern 在 Objective C 中定义一个全局变量 但我刚刚意识到我在第一个方法之前在 m 文件顶部声明的变量也意外地是全局的 这导致了一些问题 问题 我将它们移至头文件的 interface 部分 我认为这正确
  • SVN 错误:预期的 fs 格式介于“1”和“3”之间;找到格式“4”

    这就是我所做的 我已经安装了 svnserve 作为服务 并使用以下命令启动它网络启动svn服务命令 我输入了svn ls svn localhost测试该服务 但它返回了本文标题中所述的错误 我进入了svn 版本 and svnserve
  • 将一个对象属性值传输到另一个对象

    首先 我知道自动映射器 而且我不想使用它 因为我正在学习C 我想深入了解它 所以我正在尝试自己解决这个问题 如下所述 但是 我正在尝试创建一个属性复制器 以将一种类型的属性值复制到另一种类型 前提是该属性具有相同的名称和类型 并且可以从源读
  • 为什么 git 会重复添加和删除 Storyboard 部分?

    当保存故事板并将更改提交到 git 时 整个过程很可能会发生变化
  • 如何快速过滤字典并将结果输出到 CollectionViewController 中

    我正在制作一个显示口袋妖怪及其类型的应用程序 该应用程序的一部分也会显示出它们的弱点 我有一个列出所有神奇宝贝的全局变量 如下所示 var objects id 001 typeTwo Poison name Bulbasaur type
  • 对 Maybe a 进行约束,其中 Eq a

    我如何约束 Maybe a where Eq a 它必须是种类 gt 约束 我尝试过的 class a Maybe b Eq b gt K a where instance a Maybe b Eq b gt K a where Error
  • Rust 单元测试后清理的好方法是什么?

    由于测试函数会在失败时中止 因此不能简单地在被测试函数结束时进行清理 在其他语言的测试框架中 通常有一种方法可以设置一个回调来处理每个测试函数末尾的清理工作 由于测试函数会在失败时中止 因此不能简单地在被测试函数结束时进行清理 使用 RAI
  • 如何使控件正确绘制/刷新

    我有一个源自支票簿的控件 我将其称为 SettingBooleanButton 但是当将任何窗口或对话框拖动到该控件上时 该控件会保留拖动的迹象 下图显示了将应用程序窗口拖动到控件上方的效果 这是我的 OnPaint 代码块 Public
  • Famo.us IframeSurface

    我尝试在表面内实现 iframe globals define define function require exports module use strict import dependencies var Engine require
  • .NET REGEX 匹配匹配空字符串

    我有这个 pattern 0 9 0 9 Target X 113 3413475 Y 18 2054775 我想匹配数字 它与测试软件中的查找相匹配 例如http regexpal com http regexpal com 和正则表达式
  • PostgreSQL 查询约束中允许的值列表?

    给定一个名为的 PostgreSQL 表requests有一列名为status和这样的约束 ALTER TABLE requests ADD CONSTRAINT allowed status types CHECK status IN p
  • 最佳方法:访问控制允许来源多源域

    这个问题之前已经在这里被问过 并给出了一系列很好的答案 主要是 访问控制允许来源多源域 https stackoverflow com questions 1653308 access control allow origin multip
  • .htaccess 如果 url 不以扩展名结尾,则在末尾添加斜杠

    我刚刚开始学习正则表达式 但我无法弄清楚这一点 如果 URL 不包含扩展名 我需要在 URL 末尾强制添加斜杠 更清楚地说 example com test stays the same example com test php stays
  • 如何以及在哪里通过 macOS 基于 Python 的应用程序上的本机 GUI 最好地检索 sudo 密码 - (同时维护交互式输出流 (stdout))

    好的 情况是这样的 我正在使用 Python 和 wx wxphoenix 构建 macOS GUI 应用程序 用户可以使用 GUI 例如 script1 启动文件删除过程 包含在script2 为了顺利运行script2需要以 sudo