2011-12-27 143 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文本。

問候, 伊利達