在我的组织中,我们有许多运行 OS X Yosemite 的 Mac。每台机器都有一个默认帐户,我们的 IT 团队可以使用该帐户访问机器以提供 IT 帮助。我们希望定期更改此帐户的密码,并且随着组织中 mac 数量的增长,我们希望找到一种方法来自动执行此任务。
我编写了一个 Python 脚本,使用pexpect
该脚本将 SSH 连接到每台机器并执行dscl
以更改登录密码,然后通过 SSH 连接到每台机器以运行security
以更改登录钥匙串密码。
这些方法是存储新旧密码old_password
和new_password
属性的类的一部分:
def _change_login_password(self, host):
"""Change the login password of a machine.
Returns True on success, False on failure.
"""
try:
child = pexpect.spawn(
"ssh default@{} dscl . passwd /Users/default".format(host))
child.expect("Password:")
child.sendline(self.old_password)
child.expect("New Password: ")
child.sendline(self.new_password)
child.expect(
"Permission denied. Please enter user's old password:")
child.sendline(self.old_password)
child.close()
return not child.exitstatus
except pexpect.TIMEOUT:
return False
def _change_keychain_password(self, host, login_password):
"""Change the keychain password of a machine.
Changes the keychain password to match the login password.
Returns True on success, False on failure.
"""
try:
child = pexpect.spawn(
"ssh default@{} security set-keychain-password"
" login.keychain".format(host))
child.expect("Password:")
child.sendline(login_password)
child.expect("Old Password: ")
child.sendline(self.old_password)
child.expect("New Password: ")
child.sendline(login_password)
child.expect("Retype New Password: ")
child.sendline(login_password)
child.close()
return not child.exitstatus
except pexpect.TIMEOUT:
return False
这些方法都未能针对我的 OS X Yosemite 工作笔记本电脑进行测试。通过 ssh 执行的每个命令都会返回非零退出状态,并且笔记本电脑上的密码不会更改。
...但是,当我在任一方法的顶部插入pdb
断点,然后在调试器中单步执行该方法而不进行任何更改时,退出状态变为 0,并且笔记本电脑上的密码发生更改。
海森堡。
在调用周围插入打印语句pexpect
有时也会导致方法成功。
我已经尝试了pexepect
'sdelaybeforesend
属性,它在sendline
将其有效负载发送到子进程之前添加了一个延迟,认为在调试器中单步执行的时间延迟可能是问题所在,但这并没有解决问题。
有谁知道我接下来可能会看哪里?我的一些同事怀疑这可能是一个tty
问题。有谁知道pdb
可能会如何影响环境并导致这些命令成功,或者 OS X 导致它们失败的原因是什么?