关闭 Linux 之前是否仍需要执行 sync(8)?

关闭 Linux 之前是否仍需要执行 sync(8)?

sync; sync; sync; sleep 30; halt我仍然看到人们在谈论关闭或重新启动 Linux 时建议使用咒语。

我从 Linux 诞生之初就一直在使用它,尽管这是 BSD 4.2/4.3 和 SunOS 4 时代的推荐程序,但我记不起在过去至少十年中我必须这样做过,在此期间我可能经历过数千次关闭/重启 Linux。

我怀疑这是一种时代错误,因为内核无法卸载和同步根文件系统以及即使在单用户模式(例如 /tmp)下所需的其他关键文件系统,因此有必要明确告诉它将尽可能多的数据刷新到磁盘。

这些天来,还没有在内核源代码中找到相关的代码(挖掘http://lxr.linux.no和谷歌),我怀疑内核足够智能,可以干净地卸载根文件系统,并且文件系统足够智能,可以在正常shutdown/ reboot/期间卸载自身之前有效地执行同步(2) poweorff

仅在极端情况下才是"sync; sync; sync"必要的,即文件系统无法干净地卸载(例如物理磁盘故障)或系统处于只有强制直接重启(8)才能使其摆脱冻结的状态(例如负载太高而无法让它安排关机命令)。

在卸载可移动设备之前我从未执行过该sync过程,而且从未遇到过问题。

另一个例子 - Xen 允许从 Dom0 向 DomU 发送shutdown命令,这被认为是“干净关机”,无需任何人先登录并输入魔法sync; sync; sync

我是对的吗?还是说我很幸运,有几千个系统关闭?

答案1

人们之所以会sync; sync在 a 之前运行halt,是因为该halt命令无法在较旧的 Linux 上彻底关闭系统。在 SYSVr4 系统上执行此操作的正确方法一直是告诉 init 移动到不同的运行级别。

BSD 和 SunOS 4 不是 SYSVr4 操作系统,这就是它们之间的区别。Solaris(SunOS 5)是 SYSVr4,而 Linux 会挑选出它想要使用的 SYSVr4 标准的部分内容。

在大多数 UNIX 上(Linux 是例外之一),使用 halt 实际上是一种非常糟糕的方法,因为它实际上并没有运行 init 脚本来执行诸如停止进程和卸载磁盘之类的操作 - 它只是停止处理器。

如果你能保证你会绝不曾经使用过除 Linux 之外的任何类型的 UNIX 系统,那么您可以继续使用halt- 如果您有机会使用其他 UNIX,那么我建议养成使用init _runlevel_或的习惯shutdown

shutdown命令实际上告诉init改变其运行级别运行级别- 这样 init 就会继续运行与该运行级别相关的每个 K* init 脚本和 S* init 脚本。运行级别 0 中的一个脚本执行文件系统的卸载。

在 Linux 上,该halt命令只会调用shutdown命令,除非运行级别已经是 0(关闭)或 6(重新启动)反正;所以没有损失。

卸载文件系统的操作umount将在卸载之前将数据同步到磁盘。

如果你一直sync; sync; halt在 Linux 上运行,那么你将对文件系统状态感到满意,因为开发人员已经halt确保正确的事情;然而更正确的用法是:shutdown now

答案2

我可以仅有的说明为什么要发出sync多次。该命令安排刷新到磁盘,但在实际刷新完成之前返回。任何后续sync命令都将阻塞,直到任何未完成的刷新正在进行,然后才安排另一次刷新并退出。因此,sync; sync确保同步刷新。您不需要执行超过 2 次,也不需要sleep混合使用。

答案3

使用多个sync调用是为了让操作系统和磁盘有时间刷新写入队列。 "sync; sync; sync"被认为没有那么有用;一个调用确实有用,"sync<cr> sync<cr> sync<cr"而 ASR-33 执行回车/换行时的延迟提供了足够的延迟。 Halt 总是调用同步;问题是断电前是否有足够的时间刷新队列。

原始海报sync; sleep 30更符合预期。

答案4

如果您的系统已退化(例如/bin/shinit,则旧行为会重新出现。halt将看到它不知道运行级别,无法命令运行级别更改,实际上发出halt系统调用并立即关闭系统。但是,sync现在是同步的(至少从 2000 年开始就是同步的),您不需要多次运行它。

在所有其他情况下,sync之前发出命令halt不会产生任何作用。这种情况就是记住了你的训练,但没有记住背后的原因。在正常系统上,有后台作业,因此如果立即关闭系统,sync;sync;sync;halt则不会起作用。halt

相关内容