我正在尝试使用Unix pass程序自动设置新密码。 我了解有一个Python库pexpect可能会有所帮助,但我想避免使用第三方库。
使用终端时,流程如下:
$ pass insert --force gmail
>> Enter password for gmail: <type in password using masked prompt>
>> Retype password for gmail: <reenter password>
我希望我的功能做什么
pass insert --force {entry_name}
问题:
我被困在步骤2上。子进程无限期挂起,错误超时或不产生任何输出。
尝试:
代码:
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))
答案 0 :(得分:1)
编辑:最初的答案是关于passwd
的,它用于设置密码。后来我注意到您使用pass
,它是一个密钥库(实际上并没有更改Unix密码)。 pass
程序的工作方式不同,如果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均为空)。
对于passwd
命令:
仅供参考:passwd
命令将提示输出到stderr
,而不是stdout
。
注意:您可能无需在同一“写”中两次发送密码,而是需要等待第二次提示,然后再次发送密码。
对于这种简单情况,类似于您的代码应该可以工作,但是通常应该在所有管道上使用select
并在另一侧准备好时发送/接收数据,这样就不会出现死锁。