在脚本中通过`subprocess.POPEN`将密码传递给KLOG

0 投票
1 回答
537 浏览
提问于 2025-04-16 03:12

我正在写的一系列应用程序需要用户能够通过 KLOG 认证来读取文件系统。有些功能要求用户必须有 KLOG 令牌(也就是需要认证),而有些则不需要。我写了一个简单的 Python 装饰器,这样我就可以在我的模块中整理“你必须 KLOG 认证”的功能。

# this decorator is defined in ``mymodule.utils.decorators``
def require_klog(method):
    def require_klog_wrapper(*args, **kwargs):
        # run the ``tokens`` program to see if we have KLOG tokens
        out = subprocess.Popen('tokens', stdout=subprocess.PIPE)
        # the tokens (if any) are located in lines 4:n-1
        tokens_list = out.stdout.readlines()[3:-1]
        if tokens_list == []:
            # this is where I launch KLOG (if the user is not authenticated)
            subprocess.Popen('klog')
        out = method(*args, **kwargs)
        return out
    return require_klog_wrapper

# once the decorator is defined, any function can use it as follows:
from mymodule.utils.decorators import require_klog
@require_klog
def my_function():
 # do something (if not KLOGed, it SHUOLD ask for the password... but it does not!)

这其实很简单。问题出在我尝试应用以下逻辑时:“如果用户没有 KLOG 认证,就运行 KLOG 并询问密码”。

我使用 subprocess.Popen('klog') 来实现这个功能,终端确实会弹出输入密码的提示。但是,当我输入密码时,密码会在终端上显示出来,更糟糕的是,按下回车后什么也没有发生。

编辑:

在 Alex 快速且正确的回应后,我解决了这个问题,步骤如下:

  • 我删除了模块目录下所有的 *.pyc 文件(是的,这确实有影响)
  • 我使用 getpass.getpass() 来把密码存储在一个本地变量中
  • 我用 -pipe 选项调用 KLOG 命令
  • 我通过管道的 write 方法将本地存储的密码传递给管道

下面是修正后的装饰器:

def require_klog(method):
    def require_klog_wrapper(*args, **kwargs):
        # run the ``tokens`` program to see if we have KLOG tokens
        out = subprocess.Popen('tokens', stdout=subprocess.PIPE)
        # the tokens (if any) are located in lines 4:n-1
        tokens_list = out.stdout.readlines()[3:-1]
        if tokens_list == []:
            args = ['klog', '-pipe']
            # this is the custom pwd prompt 
            pwd = getpass.getpass('Type in your AFS password: ') 
            pipe = subprocess.Popen(args, stdin=subprocess.PIPE)
            # here is where the password is sent to the program
            pipe.stdin.write(pwd) 
        return method(*args, **kwargs)
    return require_klog_wrapper

1 个回答

2

看起来,你的脚本(或者它后面启动的其他东西)和运行 klog 的子进程在争抢 /dev/tty 这个资源,而子进程输掉了这场竞争(毕竟,你没有调用从 subprocess.Popen 返回的对象的 wait 方法,这样就无法确保在继续之前等它结束,所以出现某种竞争条件也不奇怪)。

如果 wait 不够用,我会通过在 Python 代码中加入

pwd = getpass.getpass('password:')

(当然,最上面要有 import getpass),然后用 -pipe 参数运行 klog,并设置 stdin=subprocess.PIPE,接着把 pwd 写入这个管道(通过调用从 subprocess.Popen 返回的对象的 communicate 方法)。

撰写回答