昨天我对 Paramiko 进行了两行代码更改,这不应该(据我所知)产生任何不利影响,然后我们的电话立即开始响起,并且收到了有关用户无法访问的报告的电子邮件他们 NFS 挂载的主目录是 zfs 文件系统。我询问了我的同事们的意见,每个人都很难理解为什么这个改变不仅没有完成我的计划,而且为什么它会为每个人都带来一切。
在使用 Paramiko 执行“zfs create”命令创建新用户的 NFS 主目录后,我使用 Python 的“time.sleep(5)”行给远程系统执行和处理命令的机会(有时特别是如果 NFS 服务器处于压力之下,命令可能需要一两秒才能真正生效)。
事实证明,我们似乎遇到了一个罕见的情况,即 5 秒的延迟是不够的。所以我决定把它从 Python 的“time.sleep(5)”函数改成使用 Paramiko 的“channel.recv_exit_status()”函数来等待退出状态码,这样花费的时间是多少是必需的(不是任意的秒数)。
以下是代码的区别(删除以减少确定 zfs 路径和用户名等平凡的东西):
原始版本:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("homedirserver.example.com")
# Create zfs share
command = "zfs create {0}/{1}".format(zfs_parent, username)
ssh.exec_command(command)
time.sleep(5)
# Confirm creation (this can fail without a time.sleep delay above)
command = "zfs list -H {0}/{1}".format(zfs_parent, username)
stdin, stdout, stderr = ssh.exec_command(command)
error = stderr.read().strip()
if error != "":
# log error, raise RuntimeError
新版本:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("homedirserver.example.com")
# Create zfs share
command = "zfs create {0}/{1}".format(zfs_parent, username)
stdin, stdout, stderr = ssh.exec_command(command) # <--- CHANGED
status = stdout.channel.recv_exit_status() # <--- NEW
# Confirm creation
command = "zfs list -H {0}/{1}".format(zfs_parent, username)
stdin, stdout, stderr = ssh.exec_command(command)
error = stderr.read().strip()
if error != "":
# log error, raise RuntimeError
似乎这样做时,“zfs create”命令作为文件服务器上的一个进程存在并且永远不会完成。 ps -eaf | grep "zfs create"
将命令显示为文件服务器上的一个进程,该进程在我 Ctrl+C 退出原始调用程序之前一直存在。最令人惊讶的是,这似乎足以彻底破坏从该服务器导出的所有 zfs 文件系统。在 Ctrl+C 并等待几分钟后,一切恢复正常,人们停止报告 NFS 中断。
这是Paramiko 1.14.1和Python 2.7.8。执行/调用机器是Solaris 11.2,远程文件服务器(进程挂起的地方)是Solaris 11.1。