1

私には 1 人のユーザーがいますtest

chageそのユーザーがコマンドでログインしたときにパスワードの変更を設定しました。

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

だから私はコマンドを実行しようとするとls

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

それから私はと接続しようとしますssh

[root@localhost ~]# ssh test@localhost
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)

これは、数字、アルパ、特殊文字の組み合わせで適切なパスワードを指定する場合など、いくつかの場合に機能します。

しかし、短いパスワードを指定したり、このようなパスワード変更でエラーが発生したりすると

[root@localhost ~]# ssh test@localhost
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

このコマンドでは、エラーBAD PASSWORD: it is too shortが発生しました。したがって、これは関数で判断できません。実行するとこのエラーが発生しますinteract.recv(-1)が、これは標準出力だと思います。これがエラーであると判断する方法はありますか。

paramiko doc を確認すると、クラスChannelに何らかのメソッドがあることがわかりましたが、このエラーはそのデータには含まれていません。recv_stderr_readyrecv_stderr

事前に助けてくれてありがとう。

4

3 に答える 3

3

簡単な答えは、カットオフがわかっている場合、シェルを呼び出す前に、関数にパスワードの長さをチェックさせることです。パフォーマンスも向上します。しかし、カットオフがわからない場合、それは機能しません。

あなたの説明からはわかりませんが、BAD PASSWORD メッセージが interact.recv(-1) から戻ってきた場合は、それが起こったことを知っており、それに応じて続行できます。std err または stdout のいずれかから戻ってくるはずなので、両方を確認してください。新しいパスワードが受け入れられた場合に返されるテキストがわかっている場合は、それも確認できます。どちらを先に取得しても、何が起こったかがわかります。関数はそこから続行できます。

于 2011-12-27T18:47:22.957 に答える
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

ループの各反復で、現在の \ 更新された、シェルからの出力テキストが解析されます。

よろしく、エルダッド

于 2014-01-02T11:19:56.330 に答える