2011-12-27 6 views
1

J'ai un utilisateur test.Comment définir le mot de passe lors du premier appel pour une commande de paramiko?

Je modifie le mot de passe lorsque l'utilisateur se connecte avec la commande chage.

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

Alors, quand je tente d'exécuter la commande 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 

Ensuite, j'essaie de se connecter avec 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: 

Et que je peux définir le mot de passe pour l'utilisateur. Si j'essaye de me connecter avec 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. 

Ensuite, je fais un peu de google et de trouver une solution pour définir le nouveau mot de passe avec invoke_shell show j'ai écrit une fonction

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) 

Cela fonctionne dans certains cas, comme lorsque nous donnons le mot de passe correct avec des chiffres, ALPA et combinaison de caractères spéciaux.

Mais quand on donne un certain mot de passe court ou une erreur se produit dans le mot de passe tel changement

[[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 

Dans cette commande, nous avons eu erreur MOT DE PASSE BAD: il est trop court donc ce je ne peux pas déterminer dans ma fonction. Je reçois cette erreur quand je fais interact.recv(-1) mais c'est la stdout je pense. Donc, est-il possible de déterminer que c'est l'erreur.

Je vérifie le doc paramiko et trouve que la classe Channel a une certaine méthode recv_stderr_ready et recv_stderr mais cette erreur ne vient pas dans ces données.

Merci d'avance pour votre aide.

Répondre

3

La réponse facile est d'avoir votre fonction vérifier la longueur du mot de passe avant d'appeler votre shell, si vous savez ce que la coupure est. Meilleure performance, aussi. Mais si vous ne connaissez pas le seuil, cela ne fonctionnera pas.

Je ne comprends pas votre description, mais si le message MAUVAIS MOT DE PASSE revient de interact.recv (-1), alors vous savez que c'est arrivé et que vous pouvez procéder en conséquence. Il semble que cela devrait revenir de std err ou de stdout, donc vérifiez les deux. Si vous savez quel texte revient si le nouveau mot de passe a été accepté, vous pouvez également le vérifier; Celui que vous recevez en premier vous dit ce qui s'est passé, et votre fonction peut continuer à partir de là.

+2

Thx @ScottHunter pour votre réponse. Je sais que l'erreur pourrait être 2-3 mots possibles. Je veux augmenter l'erreur si je reçois la sortie dans stderr sans vérifier la sortie standard. Si je dois vérifier stdout et stderr pour l'erreur, je dois vérifier chaque fois dans stdout. – Nilesh

+0

Malheureusement, si stdout est l'endroit où le message d'erreur est écrit, c'est de là que vous devez le lire. Pardon. –

+0

Okey Je vais lire STDOUT thx pour votre aide. – Nilesh

1

Les lignes suivantes pourraient être un problème et pourrait causer quelques bugs:

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

Code fix:

il sera préférable de l'utiliser de cette façon

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

maintenant chaque itération de la boucle, analysera le texte de sortie actuel mis à jour, à partir du shell.

Cordialement, Eldad

Questions connexes