2011-12-27 145 views
1

我有一个用户test如何在paramiko第一次调用命令时设置密码?

当用户使用chage命令登录时,我设置了密码更改。

chage -E 2012-01-25 -M 30 -d 0 -W 10 -I 5 test 

所以,当我尝试运行命令ls

[[email protected] ~]# ssh [email protected] "ls" 
WARNING: Your password has expired. 
Password change required but no TTY available. 
You have new mail in /var/spool/mail/root 

然后我尝试用ssh

[[email protected] ~]# ssh [email protected] 
You are required to change your password immediately (root enforced) 
Last login: Tue Dec 27 09:55:55 2011 from localhost 
WARNING: Your password has expired. 
You must change your password now and login again! 
Changing password for user test. 
Changing password for test. 
(current) UNIX password: 

而且比我可以设置用户密码进行连接。

如果我尝试将其与paramiko连接。

In [1]: import paramiko 

In [2]: ssh_conn = paramiko.SSHClient() 

In [3]: ssh_conn.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 

In [4]: ssh_conn.load_system_host_keys() 

In [5]: ssh_conn.connect('n2001', username='root_acc23', password='test') 

In [6]: a = ssh_conn.exec_command('ls') 

In [7]: print a[2].read() 
WARNING: Your password has expired. 
Password change required but no TTY available. 

然后我做了一些谷歌并找到了一些解决方案,与invoke_shell秀我写一个函数来设置新密码

def chage_password_change(ssh_conn, password, curr_pass): 
    ''' 
    If got error on login then set with interactive mode. 
    ''' 
    interact = ssh_conn.invoke_shell() 
    buff = '' 
    while not buff.endswith('UNIX password: '): 
     resp = interact.recv(9999) 
     buff += resp 
    interact.send(curr_pass + '\n') 

    buff = '' 
    while not buff.endswith('New password: '): 
     resp = interact.recv(9999) 
     buff += resp 

    interact.send(password + '\n') 

    buff = '' 
    while not buff.endswith('Retype new password: '): 
     resp = interact.recv(9999) 
     buff += resp 

    interact.send(password + '\n') 


    interact.shutdown(2) 
    if interact.exit_status_ready(): 
     print "EXIT :", interact.recv_exit_status() 

    print "Last Password" 
    print "LST :", interact.recv(-1) 

这是工作在某些情况下,就像当我们给同位正确的密码,ALPA和特殊字符组合。

但是,当我们给一些短密码或错误发生在更改密码这样

[[email protected] ~]# ssh [email protected] 
You are required to change your password immediately (root enforced) 
Last login: Tue Dec 27 10:41:15 2011 from localhost 
WARNING: Your password has expired. 
You must change your password now and login again! 
Changing password for user test. 
Changing password for test. 
(current) UNIX password: 
New password: 
Retype new password: 
BAD PASSWORD: it is too short 

在此命令,我们得到了错误错误密码:太短所以这个我不能在我的函数来确定。当我做interact.recv(-1)时,我得到这个错误,但这是我想的标准输出。那么有什么方法可以确定这是错误吗?

我检查paramiko文档,发现Channel类有一些方法recv_stderr_readyrecv_stderr但这个错误没有出现在该数据。

Thx为您的帮助提前。

回答

3

简单的答案是让你的函数检查密码的长度,然后再调用你的shell,如果你知道截断是什么的话。性能也更好。但是,如果你不知道截止时间,那就行不通了。

我不清楚你的描述,但是如果BAD PASSWORD消息从interact.recv(-1)返回,那么你知道它发生了,并且可以相应地继续。它似乎应该从std err或stdout回来,因此请检查两者。如果您知道接受新密码时会返回哪些文本,那么您也可以检查该密码;无论你先得到什么,都会告诉你发生了什么,你的功能可以从那里继续。

+2

THX @ScottHunter您的回复。我知道错误可能是2-3个可能的单词。我想,如果我在标准错误获取输出,而不检查标准输出,以提高错误。如果我要检查错误输出和错误然后我在标准输出每一次检查。 – Nilesh 2011-12-28 04:00:44

+0

不幸的是,如果stdout是被写入错误消息,其中,这就是你必须从阅读它。抱歉。 – 2011-12-28 15:32:42

+0

奥基我会从STDOUT THX的帮助阅读。 – Nilesh 2011-12-29 05:46:36

1

下面的几行可能是有问题的,可能会导致一些错误:

while not buff.endswith('Retype new password: '): 
     resp = interact.recv(9999) 
     buff += resp // this will append the output from the shell 

代码修复:

它将更好地使用这种方式

while not buff.endswith('Retype new password: '): 
    resp = interact.recv(9999) 
    buff = resp 

现在的每一次迭代循环,将解析当前\更新,输出从shell文本。

问候, 伊利达