如何永久关闭交换空间?

使用交换空间会使我的系统变得很慢,而关闭它则会让一切更加流畅。我有3.5GB的内存。

我知道如何通过在终端中输入sudo swapoff -a来关闭交换空间,但这只是针对当前会话,因为重新启动后交换空间会自动打开。有没有办法永久关闭交换空间呢?


3据我所知,交换空间用于休眠。只是随便说一下。 - DanMan
2是的,但它仍然可以使用。我有一个小脚本,在系统进入休眠时挂载交换分区,并在系统恢复时卸载它。在此期间,交换文件不需要处于活动状态。 - animaletdesequia
简单来说,在/etc/rc.local中加入swapoff -a,然后就可以忘记它了... ;) - user264467
2@user264467:每次重启都禁用交换空间,这样做相当违反直觉。更好的做法是永久禁用它,这样会更加清晰简洁。 - karatedog
6个回答

可以我建议一个更安全的方法吗?你永远不知道交换(swap)什么时候能帮你避免崩溃。虽然交换确实会减慢计算机的速度,但如果你使用了一个占用了所有内存的程序,有交换的能力可以帮助你避免硬重启。当计算机开始交换时,你会注意到并能够关闭问题应用程序。
所以,与其完全禁用交换,只需确保你的操作系统非常少地进行交换。这由`/etc/sysctl.conf`中的`vm.swappiness`设置控制。如果我没记错的话,Ubuntu的默认设置是`60`,对于大多数情况来说太高了,即使还有可用的内存,也会导致开始交换。如果你降低这个值,你将能够在紧急情况下保持交换的安全线。因此,打开文件:
sudo nano /etc/sysctl.conf

并在其中添加这一行:
vm.swappiness=10

如果还是太多的话,把10改成1。现在,在你重新启动后,只有在绝对必要时才会进行交换,而你可以简单地忘记它。

我喜欢改变交换物,但已经好几年没这么做了。谢谢你的提醒。sudo 给 turdon 点赞! - Darth Egregious
23只是为了补充“更安全的方法”这个论点:当你没有交换空间并且系统内存耗尽时,Linux的OOM(内存不足)杀手就会被调用。它根据一个“糟糕程度”评分选择一个进程,然后...将其终止(关闭),应用程序没有机会保存其更改、清理等。因此,如果你关闭交换空间并且内存耗尽,如果重要进程在OOM杀手眼中得分低,你很有可能丢失工作。所以,只有在你确信永远不会耗尽内存的情况下才应该关闭交换空间。 - Reid
7@Reid 值得指出的是,显然,如果你的交换空间用完了,同样的情况也会发生。 - o0'.
如果我把交换空间(swap)改为0会怎样呢?那会有什么结果?0的意思是除非绝对必要,否则不使用交换空间,对吗? - Alex Li
@AlexLi 不,10已经代表了这个意思。设置为10,你几乎不会看到任何交换。将其设置为0不是一个好主意,严肃地说,交换有时确实可以帮助你节省资源,并且设置一个较低的swappiness值可以解决你的问题而不会使系统不稳定。我没有测试过这个,但据推测,将其设置为0将禁用交换并引发与缺少交换相关的所有问题。 - terdon
17这实际上并没有回答问题。在拥有16GB或32GB内存的系统上完全禁用交换空间是有道理的。对于占用大量内存的应用程序来说,几个额外的GB的交换空间并没有任何好处,而大量的交换空间(例如20GB)会占用大量硬盘/SSD空间。此外,使用32GB内存进行休眠是_不_ _愉快_的。 - jmiserez
@jmiserez 1) 我的回答是在这里提供了两种忽略交换分区的方法之后发布的,所以我用“我可以提供一个替代方案吗?”开头。2) 实际上,几个G的交换空间可以让系统完全不同,当进行交换时,系统通常会明显变慢,而1或2个G的交换空间可能足够让您有足够的时间终止有问题的进程,而不必处理OOM。3) 这些方法都无法恢复您的交换分区,所以您关于硬盘空间的观点是无关紧要的。4) 我甚至没有提到休眠。 - terdon
1)&2)挺好的。 3)只要禁用交换空间,使用gparted轻松恢复空间。 4)在Ubuntu上,休眠使用交换分区,所以它们共享相同的命运。 5)FYI:一旦内存用尽,您还可以使用“zram-config”软件包启用内存压缩。这也可以为您提供一些喘息的机会来处理失控的进程。 - jmiserez
自从我在我的笔记本电脑上安装了一个512GB的固态硬盘(将近3年前),我就没有设置任何交换分区。起初我有8GB的内存,现在我有16GB。实际上,我从来没有遇到过任何问题,而且我也不想浪费我的固态硬盘空间用于交换和休眠。 - Consumology
12在某些设置中,一旦物理内存用尽并开始交换,系统就会变得“吃力”,无法使用。是的,在理论上你可以进入并终止问题源头,但当在用户界面中切换焦点需要20分钟以上,甚至通过SSH获取密码提示需要更长时间时,内存耗尽最终成为最佳选择(其次是强制重启,再次是进入并解决问题)。 - BCS
从我的经验来看,当系统没有足够或没有可用的交换空间时,通常会出现“吸泥”现象;具体表现为系统陷入一个连续循环中,不断地在硬盘上寻找不存在的可用交换空间,因此永远无法找到。过去我曾通过将swappiness值恢复到60并增加交换分区的大小来解决这个问题;你知道,正是swappiness的作用防止了“吸泥”现象的发生。 - mchid
1在我遇到这个问题的大多数情况下,它是由于过度承诺造成的(例如,一个错误导致我的项目分配和使用了比我可用的空间多几十GB)。虽然从理论上讲,这可能最终会解决,但需要花费很长时间,我不愿意等待,只能强制重启系统。我想要的是一种能够在不重启的情况下有机会恢复的解决方案。实际上,这需要通过OOM(内存溢出)杀死正确的罪魁祸首来实现。 - BCS
2@mchid 当界面冻结到改变Windows需要5分钟,等待命令执行需要10分钟时,你提出的解决方案是不可行的。即使你清楚自己在做什么,这已经够长时间了,但如果你需要运行多个命令来找到最严重的内存问题,那么所需时间可能会乘以3倍。例如,你的drop_caches命令会创建3个进程(echo、sudo、tee),当系统正在交换内存时,这可能需要很长时间。顺便说一下,我并不是在开玩笑。我的交换空间位于一个慢速硬盘上,而且在没有强制重启的情况下从OOM中恢复大约需要一个小时。 - fat-lobyte
2@mchid 我对这个问题的“解决方案”是关闭交换空间。就我个人而言,我宁愿让进程崩溃,也不愿意整个系统完全锁死。“如果你的系统在进行交换,你不应该有任何问题”,这就是我的观点:我确实遇到了很多问题。ZRAM在过去是一个不错的想法,但实际上它带来的伤害大于好处。而且,“在遇到问题之前运行命令”要求我不断关注系统内存。这不是我或大多数人使用计算机的方式,也不应该是。设备为我服务,而不是相反。 - fat-lobyte
1@mchid,我完全同意fat-lobyte的观点,不幸的是。我有一个快速的SSD用于交换空间,但它仍然需要很长时间,而且无法使用;这是由于我的错误代码引起的。我强烈倾向于杀掉系统并重新启动。我们两个都没有提供一个“更好”的解决方案,然而,杀掉进程比交换更好;后者在我的机器上也需要30分钟(直到OOM杀掉进程)。这真是一场噩梦。 - Mayou36
1@mchid请不要在评论区进行长时间的对话。请将其转移到聊天室或其他任何不会提醒我的地方。 - terdon

找到/etc/fstab文件中关于swap的那一行,并将其注释掉。我的是这样的:
UUID=6880a28d-a9dc-4bfb-ba47-0876b50e96b3 /               ext4    errors=remount-ro 0       1
UUID=7350e6f2-e3a7-4d80-9a95-8741c7db118f /home           ext4    defaults        0       2
UUID=E2E26AD1E26AAA0D /media/windows  ntfs    defaults,umask=007,gid=46 0       0

# Swap a usb extern (3.7 GB):
#/dev/sdb1 none swap sw 0 0

你可以用gedit编辑这个文件。先备份一下,以防万一:
sudo cp /etc/fstab /etc/fstab_backup
gksu gedit /etc/fstab

只需在交换位置的行开头添加#,然后重新启动计算机。
或者尝试使用命令行方式在/etc/fstab文件中注释掉交换条目。
sudo sed -i.bak '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

当我输入gksu gedit /etc/fstab时,我得到了以下内容:# /etc/fstab: 静态文件系统信息。 # # 使用 'blkid' 命令打印设备的通用唯一标识符(UUID); # 这可以与 UUID= 一起使用,作为更可靠的设备命名方式, # 即使磁盘被添加或移除也能正常工作。参见 fstab(5)。 # # <文件系统> <挂载点> <类型> <选项> <转储> <检查> /host/ubuntu/disks/root.disk / ext4 loop,errors=remount-ro 0 1 /host/ubuntu/disks/swap.disk none swap loop,sw 0 0 - Alex Li
1那么,按照他说的去做。注释掉第一行提到“交换”的部分。 :P - cHao

错误..如果systemd在任何驱动器上找到一个SWAP分区,它都会自动挂载它。 奇怪的是没有人提到systemd。解决方案其实很简单;要永久禁用交换空间,你必须:
1. 执行swapoff -a 2. 编辑/etc/fstab并注释掉任何存在的交换条目(如果有的话,你可能可以跳过这一步,只执行步骤3也可能适用于你)。 3. 运行:sudo systemctl mask "dev-sdXX.swap"(其中XX是交换分区的代号。注意,在单位名称周围使用引号,以防名称中有转义字符/反斜杠。还有一个有用的提示是对所有可能的分区都这样做,这样如果在任何其他驱动器上有一个交换分区,它将不会被挂载)。
祝好。

3数字3赢了!! - oneklc
13号是Ubuntu 18.04的必备条件,可能是因为从16.04升级到18.04,或者可能是因为在nvme上进行安装。 - vigilian
我们有没有相反的指令只是为了知道? - vigilian
3sudo systemctl unmask dev-sdXX.swap - tgwaste

只需从fstab中删除该条目(或在行前使用#进行注释),然后重新启动即可。查找包含单词“swap”的那一行。
sudo nano /etc/fstab

12这个也可以,但我认为最好是对该行进行注释,而不是完全删除它,以防您想要撤销更改。 - animaletdesequia
1我已经编辑了我的帖子。 - mdalacu

补充 Zibri的答案

  • swapoff -a会暂时禁用所有交换。
  • 如果在/etc/fstab中有一些交换,请将其注释掉并重新启动。
  • 在我的情况下(OdroidMC1+Armbian),交换由systemctl控制。要找到负责的交换,请使用systemctl --type swap

示例:

# systemctl --type swap

UNIT           LOAD   ACTIVE SUB    DESCRIPTION                                                                                                                                                                     
dev-zram1.swap loaded active active /dev/zram1                                                                                                                                                                      

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

1 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

通过使用sysctl将其屏蔽禁用:
# systemctl mask dev-zram1.swap

Created symlink /etc/systemd/system/dev-zram1.swap → /dev/null.

感谢您的贡献!请注意,由于我们采用问答格式,您无法回复其他答案或评论。最好尝试以不引用其他答案的方式撰写您的答案,因为现有答案可以修改。同时,跟随可能相互冲突的两个答案也会令人困惑。如果您需要引用其他内容,请确保使用永久链接,因为用户名也可能随时间变化。 - Nmath

永久禁用交换空间

swapoff -a                 # Disable all devices marked as swap in /etc/fstab
sed -e '/swap/ s/^#*/#/' -i /etc/fstab   # Comment the correct mounting point
systemctl mask swap.target               # Completely disabled

注意:所有命令都应以root权限运行。