代码之家  ›  专栏  ›  技术社区  ›  Brian H.

如何使用python使用unix pass命令行程序自动设置密码

  •  0
  • Brian H.  · 技术社区  · 8 年前

    我正在尝试使用Unix pass程序自动设置新密码。 我知道有一个python库, pexpect ,这可能有帮助,但我希望避免使用第三方库。

    使用终端时,流程如下所示:

    $ pass insert --force gmail
    >> Enter password for gmail: <type in password using masked prompt>
    >> Retype password for gmail: <reenter password>
    

    我希望我的函数做什么:

    1. 运行命令 pass insert --force {entry_name}
    2. 捕获输出(并回显以进行测试)
    3. 检查输出是否存在“gmail密码”,如果为真
      • 将{password}\n'写入stdin
      • 再次将{password}\n'写入stdin
    4. 回显任何错误或消息以进行测试

    问题:

    我被困在第二步。子进程要么无限期挂起,要么因错误而超时,要么不产生输出。

    尝试:

    • 我尝试了Popen()的配置,同时使用stdin.write()和communicate()。
    • 我已经在不同点设置了wait()调用。
    • 我尝试过shell=true和shell=false选项(出于安全原因,更喜欢false)

    代码 :

    def set_pass_password(entry_name, password):
        from subprocess import Popen, PIPE
    
        command = ['pass', 'insert', '--force', entry_name]
    
        sub = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
    
        # At this point I assume that the command has run, and that there is an "Enter password..." message
        message = sub.stdout.read()  # also tried readline() and readlines()
        print(message) # never happens, because process hangs on stdout.read()
    
        if 'password for {}'.format(entry_name) in message:
            err, msg = sub.communicate(input='{p}\n{p}\n'.format(p=password))
            print('errors: {}\nmessage: {}'.format(err, msg))
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Leo K    8 年前

    编辑:最初的答案是 passwd ,这是过去 设置 密码我很晚才注意到你用 pass ,这是一个密钥库(实际上不会更改Unix密码)这个 通过 程序的工作方式不同 不会的 如果 stdin 不是tty因此,以下非常简单的程序可以工作:

    def set_pass_password(entry_name, password):
        from subprocess import Popen, PIPE
    
        command = ['pass', 'insert', '--force', entry_name]
    
        sub = Popen(command, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE)
    
        err, msg = sub.communicate(input='{p}\n{p}\n'.format(p=password))
        print('errors: {}\nmessage: {}'.format(err, msg))
    
    if __name__ == "__main__":
        set_pass_password("ttt", "ttt123asdqwe")
    

    (如果命令成功,您将看到stderr和stdout都是空的)。

    对于 通行证 命令:

    仅供参考: 通行证 命令将提示输出到 stderr ,不是 stdout .

    注意:与其在同一个“write”中发送两次密码,不如 可以 在再次发送密码之前,需要等待第二个提示。

    对于这个简单的例子,与您的代码类似的代码应该可以工作,但是通常您应该使用 select 在所有管道上,当另一端准备好时发送/接收数据,这样就不会出现死锁。