内置的reboot()
函数在Ubuntu 14.04和FreeBSD 10.x主机上均能正常运行,但在Ubuntu 16.04主机上已损坏。
在Ubuntu 14.04上发生了什么:
重新启动Fabric重新连接后,我收到这样的输出,并且系统重新启动。
[ubuntu] out:
[ubuntu] out:
[ubuntu] out: Broadcast message from root<strong i="9">@ubuntu</strong>
[ubuntu] out:
[ubuntu] out: (/dev/pts/0) at 15:02 ...
[ubuntu] out:
[ubuntu] out:
[ubuntu] out:
[ubuntu] out:
[ubuntu] out: The system is going down for reboot NOW!
[ubuntu] out:
[ubuntu] out:
在Ubuntu 16.04上发生了什么:
如果在这种状态下按Enter键,Fabric实际上会继续,但之前会显示此消息:
No handlers could be found for logger "paramiko.transport"
Warning: sudo() received nonzero return code -1 while executing 'reboot'!
我正在使用以下代码重新启动:
def reboot_():
with settings(warn_only=True):
print 'rebooting'
start_time = time.time()
reboot(wait=1200)
print 'reboot took: {} seconds'.format(time.time() - start_time)
与run('reboot')完全相同
与手动run
是不足为奇的-显然有关Ubuntu对重启,SSH连接等的处理有所变化。
没有什么明显的想法,但是reboot()
(Fab的,不是Linux的)是非常基本的-它只是调用sudo('reboot')
,并临时调整Fabric的常规重新连接设置,这样它就可以在非平凡的重新启动序列之后进行重新连接(相对于默认设置,后者会很快放弃)。
参见https://github.com/fabric/fabric/blob/c0224a52df59821f21a8c0bd47ce15e42c2046a4/fabric/operations.py#L1244-您可能想要尝试进行调整。
另外,请尝试启用Paramiko的日志记录(请参阅疑难解答页面的底部-http://www.fabfile.org/troubleshooting.html),因为这可能会产生一些线索。
实际上,经过深思熟虑,听起来好像Ubuntu的reboot
从未以某种方式从不退出或将退出代码提交给Fabric的执行处理程序( run
/ sudo
),因为您注意到sudo
是在等待后将Enter混搭时变得生气的东西。
如果您查看reboot()
代码,它期望sudo('reboot')
调用最终会退出,因此它可以A)稍等一下,B)启动重新连接。
在Fabric的最后,执行只是在sudo
中徘徊的事实,这意味着有些事情远非如此。 有点奇怪。 _也许_是Fabric本身的错误,但更像是远程的不良行为。 (PS:您在哪个织物版本上看到此信息?)
意外的想法-我们可以在timeout=
上设置sudo
,然后在其周围设置except TimeoutException: pass
。 这样可以确保即使在这种(奇怪的)情况下,我们也默认尝试重新连接。
唯一的缺点是reboot
实际上正在挂起并且系统没有真正地重新启动,但这不像我们通过上述更改使该情况变得更糟–无限挂起只会在这种情况下发生连接循环,而不是sudo
。
以下是Ubuntu 16.04中另一个非常奇怪的,已更改的行为。 当我在ssh会话中运行poweroff
时,计算机确实关闭了电源,但是SSH会话挂起了! 无法使用Ctrl + C或Ctrl + D或任何其他方式。 我所能做的就是等待_lot_然后ssh中止:
packet_write_wait: Connection to 192.168.56.11: Broken pipe
我确实不十分了解SSH连接处理,但这可能与重新启动完全一样。
我刚刚遇到了严重的重启(AWS上的最新Ubuntu 16.04,Fabric == 1.12.0),但是使用了另一种方式。 对我来说,它只是抛出:
Fatal error: sudo() received nonzero return code -1 while executing!
Requested: reboot
Executed: sudo -S -p 'sudo password:' /bin/bash -l -c "reboot"
手动在终端中运行sudo reboot
可以正常工作(主机重新启动)。
可能值得注意:
$ readlink /sbin/reboot
/bin/systemctl
$ readlink /sbin/shutdown
/bin/systemctl
还有另一件事。 我将重新启动代码更改为使用aws-cli,并且在调用之后(大约需要1秒,似乎是异步的),我运行sudo('add-apt-repository --yes ppa:nginx/stable')
。 它一直都有效,但是现在在重新启动后,它也返回了-1:
sudo: add-apt-repository --yes ppa:nginx/stable
Fatal error: sudo() received nonzero return code -1 while executing!
Requested: add-apt-repository --yes ppa:nginx/stable
Executed: sudo -S -p 'sudo password:' /bin/bash -l -c "add-apt-repository --yes ppa:nginx/stable"
然后,我尝试通过添加fabric.network.disconnect_all()
来使结构重新连接。 结果导致要求输入密码(为什么?):
[...] sudo: add-apt-repository --yes ppa:nginx/stable
[...] Login password for 'ubuntu':
而且它仅在重启后添加了time.sleep(60 * 3)
后才开始工作。 这显然是一个差劲的创可贴,现在我很困惑如何正确处理密码问题。 看起来与此问题有关。
问题似乎是在命令状态通过ssh连接返回之前,“重新引导”现在有时有时“太快”。
(提示:如果结果是处于冻结的ssh连接:键入\n~.
aka enter,波浪号,句点。这是默认的ssh转义字符,然后是ssh的断开连接命令。如果您尝试ctrl- c或ctrl-d,ssh尝试将其传递给另一端运行的进程。)
一种解决方案是使用shutdown -r +1
,它将在下一分钟安排重新启动,然后等待一分钟以使其重新启动,然后开始尝试重新连接。 诚然,等待一分钟并不是很好。
可以尝试的骇人听闻的东西: shutdown -r +0
应该等效于reboot
,但是在我有限的对VirtualBox中运行的Ubuntu-16.04的测试中,它往往会花一秒钟的时间,显示下一个在断开手动ssh会话之前的shell提示。
这可能是#1444的重复
如果将初始化守护程序切换为新贵,则重新启动将按预期进行。 看来systemd立即杀死了sshd。
Debian / Ubuntu的systemd软件包中存在一个错误,该错误在关机时在SSH之前就杀死了网络服务,因此一切都挂起了。
它已固定在最新的发行版中。 不知道Ubuntu软件包的状态。
在某些脚本中,我还遇到了有关reboot()用法的问题。 我发现使用密码连接时,重新启动正常进行,但是使用密钥文件身份验证时,连接挂起(重新启动已完成)。
ubuntu错误https://bugs.launchpad.net/ubuntu/+source/openssh/+bug/1645002被标记为已在16.10中修复,但尚未在16.04中修复,并且尚不清楚何时修复。
对我来说,当前行为是paramiko / fabric立即检测到ssh连接已关闭,但是这是在paramiko / fabric看到重新启动命令完成之前。 至少它不会像原始报告中那样无限期地挂起。
Fatal error: sudo() received nonzero return code -1 while executing!
...
Aborting.
Plain reboot()
在针对AWS EC2和本地virtualbox VM的一系列测试中始终为我做到了这一点。 (我一直使用密钥文件身份验证。)
正如我建议的那样,我发现了一个简短而优雅的解决方法,上面没有太多详细信息:
reboot(command="shutdown -r +0")
这对我来说是预期的效果(在我针对AWS EC2和本地virtualbox VM进行的少数测试中,它们都运行了最新的ubuntu 16.04)。 请注意,“ shutdown -r now”的行为类似于“ reboot”,并且似乎不起作用。
我快速浏览了freebsd和openbsd手册页,看起来它们具有支持这些参数的shutdown命令。 我怀疑命令“ shutdown -r +0”几乎可以在所有“ reboot”的unix系统上使用。 因此可以考虑更改默认命令或更新文档。 (但是我很想先看到有关BSD系统的测试报告。)
shutdown -r +0
对我们来说还不够。 由于重新启动不接受手动超时,因此我什至尝试了以下方法:
try:
sudo("shutdown -r +0", timeout=300)
except NetworkError:
pass
# in case the sudo times out during reboot
sleep(15)
尽管挥舞着所有的手,但下一个命令会无限期地挂起。 连接池是否可能保持(并使用)死连接? 如果是这样,是否有解决方法? 我可以暂时减少连接级别的超时吗?
确实,您需要用reboot()
的方式替换现有连接:
https://github.com/fabric/fabric/blob/1.13.2/fabric/operations.py#L1289 -L1294
道歉以恢复旧的问题,我还可以确认在尝试重新启动LXC容器时发生此问题。 @ploxiln使用command="shutdown -r +0"
确实对我们有用。
在全新安装了bash的FreeBSD 11.1上确认此错误:
reboot(wait=1)
结果:
Fatal error: sudo() received nonzero return code -1 while executing!
Requested: reboot
Executed: sudo -S -p 'sudo password:' /usr/local/bin/bash -l -c "reboot"
Aborting.
Traceback (most recent call last):
…
raise env.abort_exception(msg)
hosts.FabricException: sudo() received nonzero return code -1 while executing!
在结束@ ambsw-technology和@ploxiln注释后,我最终需要用它来使事情顺利进行。 我正在针对Ubuntu 16.04 LTS服务器(从Windows客户端)运行。
sudo('shutdown -r +0')
time.sleep(30)
fabric.state.connections.connect(env.host_string)
仅供参考,对于18.04.2 LTS服务器,我仍然看到了这一点。
有什么解决办法吗? 16.04也有问题
最有用的评论
ubuntu错误https://bugs.launchpad.net/ubuntu/+source/openssh/+bug/1645002被标记为已在16.10中修复,但尚未在16.04中修复,并且尚不清楚何时修复。
对我来说,当前行为是paramiko / fabric立即检测到ssh连接已关闭,但是这是在paramiko / fabric看到重新启动命令完成之前。 至少它不会像原始报告中那样无限期地挂起。
Plain
reboot()
在针对AWS EC2和本地virtualbox VM的一系列测试中始终为我做到了这一点。 (我一直使用密钥文件身份验证。)正如我建议的那样,我发现了一个简短而优雅的解决方法,上面没有太多详细信息:
这对我来说是预期的效果(在我针对AWS EC2和本地virtualbox VM进行的少数测试中,它们都运行了最新的ubuntu 16.04)。 请注意,“ shutdown -r now”的行为类似于“ reboot”,并且似乎不起作用。
我快速浏览了freebsd和openbsd手册页,看起来它们具有支持这些参数的shutdown命令。 我怀疑命令“ shutdown -r +0”几乎可以在所有“ reboot”的unix系统上使用。 因此可以考虑更改默认命令或更新文档。 (但是我很想先看到有关BSD系统的测试报告。)