如何修改“/sys/kernel/mm/transparent_hugepage/enabled”?

我使用的是MongoDB 3.0版本,发现了一个警告:
MongoDB shell version: 3.0.0
connecting to: test
Server has startup warnings: 
2015-03-13T16:28:29.405+0800 I CONTROL  [initandlisten] 
2015-03-13T16:28:29.406+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2015-03-13T16:28:29.406+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2015-03-13T16:28:29.406+0800 I CONTROL  [initandlisten] 
2015-03-13T16:28:29.407+0800 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2015-03-13T16:28:29.407+0800 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2015-03-13T16:28:29.407+0800 I CONTROL  [initandlisten]

~# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never

~# cat /sys/kernel/mm/transparent_hugepage/defrag
[always] madvise never

我尝试使用回声,但它不是永久的,在重新启动后会被重置。
echo never > /sys/kernel/mm/transparent_hugepage/defrag

如何永久修改`/sys/kernel/mm/transparent_hugepage/enabled`?

1以下可能有很好的答案,但在我个人看来,你应该查看MongoDB的官方文档:http://docs.mongodb.org/master/tutorial/transparent-huge-pages/ - hgoebl
7个回答

你可以
1. 安装 `sysfsutils` 软件包: ``` sudo apt install sysfsutils ```
2. 并在 `/etc/sysfs.conf` 文件中添加以下设置行: ``` kernel/mm/transparent_hugepage/enabled = never ```
这是最干净的解决方案,因为它将所有的sysfs配置都集中在一个地方,而不是依赖于自定义的启动脚本。其他答案中的脚本和条件表达式适用于如果你不知道内核将通过哪个路径暴露该设置,即如果你甚至对受影响机器上运行的内核版本没有大致的了解。

4这在我使用的Ubuntu 14.04上的AWS EC2实例上没有任何作用。我对sysfs.conf不太了解,但它似乎是一个受Ubuntu支持的配置,然而该文件之前并不存在于我们的系统中,添加它并重新启动后,mongo输出的警告没有任何变化。我还尝试了clayzermk1下面的建议,'defrag'警告仍然出现。官方的mongo文档初始化脚本确实移除了这两个警告。 - Neek
cat /sys/kernel/mm/transparent_hugepage/enabled 的输出是什么?它是否存在?sysfs.conf 通常由 /etc/init.d/sysutils 在启动时进行评估。它是否已启用?当您调用 /etc/init.d/sysutils start 时会发生什么? - David Foerster
$ cat /sys/kernel/mm/transparent_hugepage/enabled [always] madvise never $ ls -l /etc/sysfs.conf ls: 无法访问 /etc/sysfs.conf: 没有那个文件或目录 $ ls -l /etc/init.d/sysutils ls: 无法访问 /etc/init.d/sysutils: 没有那个文件或目录 这些 AWS EC2 Ubuntu 实例似乎没有安装 sysutils。由于推荐的Mongo文档已经解决了我的问题,我不确定自己在做什么的情况下,我不愿意安装 sysutils 并对 EC2 实例进行更改。 - Neek
我对EC2的不同系统配置并不感到惊讶。这正是它们在这里属于离题的原因。 - David Foerster
3我也没有 sysfs.conf 文件和 /etc/init.d/sysutils。Ubuntu 16.04。 - HEX
这不应该是/etc/sysctl.conf吗? - unhammer
1@unhammer:不,这两者的范围是不同的。sysctl用于设置,你也可以通过内核参数来实现;而sysfs.conf用于/sys目录中的条目。 - David Foerster
在Ubuntu 16.04上使用systemd,因此在更改/etc/sysfs.conf后,需要使用systemctl restart sysfsutils.service重新启动sysfsutils服务...这对我来说起到了作用。 - Thomas Urban
@cepharum:是的,sysfs.conf会被一个服务读取(通常在启动时)。其他版本的Ubuntu也是如此。 - David Foerster
@DavidFoerster 我的评论确实有些含糊不清,我基本上是在提到为什么在Ubuntu 16.04及更高版本中缺少/etc/init.d/sysutils的原因... - Thomas Urban
这并不能解决/sys/kernel/mm/transparent_hugepage/defrag的警告 - orszaczky
@orszaczky:就我理解来说,那不是问题的关键。您可以随时提出新问题。 :-) - David Foerster
在按照答案操作后,我仍需要运行 systemctl daemon-reload,然后再运行 systemctl restart mongodb 才能消除错误(在Ubuntu 17.04上)。 - Yohanes Gultom
@YohanesGultom:显然,这个设置只能应用于新创建的进程。这仅适用于在运行时修改了设置的情况,即不包括启动时的设置,这意味着它超出了本问题的范围。 - David Foerster
对我来说,似乎在这个设置更改之前redis-server已经启动了。如果我查看shell命令cat /sys/kernel/mm/transparent_hugepage/enabled或重新启动redis,一切都正常。你有什么想法吗? - navossoc
1@navossoc:如果你有新的问题或者跟进问题,请打开一个新的问题。评论区不适合或者用于新问题或者延伸讨论。你可以给我留言并通知我,以引起我的注意。谢谢。 - David Foerster
我发现这是在Ubuntu 18.04中最简单且最干净的解决方法,可以持久地禁用THP。 - SteamerJ

MongoDB文档提供了一些建议。http://docs.mongodb.org/manual/reference/transparent-huge-pages/ "首选"的方法是编辑/etc/default/grub,并在GRUB_CMDLINE_LINUX_DEFAULT后附加transparent_hugepage=never,然后运行update-grub来重新构建GRUB配置。
以下两行代码将完成此操作。请确保验证输出!
sed -r 's/GRUB_CMDLINE_LINUX_DEFAULT="[a-zA-Z0-9_= ]*/& transparent_hugepage=never/' /etc/default/grub | sudo tee /etc/default/grub
sudo update-grub

请注意,update-grubgrub-mkconfig的包装器。 grub-mkconfig将使用/etc/default/grub.d/*中的条目覆盖/etc/default/grub中的条目。 如果您恰好在AWS上运行,请改为编辑/etc/default/grub.d/50-cloudimg-settings.cfg
"备用"方法是编辑/etc/rc.local并在exit 0之前添加以下内容:
if test -f /sys/kernel/mm/transparent_hugepage/khugepaged/defrag; then
  echo 0 > /sys/kernel/mm/transparent_hugepage/khugepaged/defrag
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
  echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
  echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi

就我个人而言,我最终采用了“首选”和“备选”两种方法,因为它们并不互斥,并且可以消除关于碎片整理的警告。
* 在Ubuntu 14.04、MongoDB 3.0.2和AWS上对我有效。

我在DigitalOcean上的一键式MongoDB应用服务器上尝试了这个,但没有成功。仍然收到相同的警告信息。 - scaryguy
感谢您提到EC2和50-cloudimg-settings.cfg的部分。 - Martin Konecny

这是一个在AWS EC2上经过测试可在Ubuntu 16.04上运行的解决方案。Ubuntu 16.04使用systemd init系统,而此配置文件表达了在MongoDB启动之前应更改这些设置。
创建一个名为/etc/systemd/system/mongodb-hugepage-fix.service的文件,并添加以下内容:
[Unit]
Description="Disable Transparent Hugepage before MongoDB boots"
#WARN: check service name on your system
# If you are using MongoDB Cloud, service name is "mongodb-mms-automation-agent.service"
Before=mongodb.service      

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled'
ExecStart=/bin/bash -c 'echo never > /sys/kernel/mm/transparent_hugepage/defrag'

[Install]
#WARN: check service name on your system
# If you are using MongoDB Cloud, service name is "mongodb-mms-automation-agent.service"
RequiredBy=mongodb.service

将文件加载到systemd中:
systemctl daemon-reload

激活文件作为MongoDB的引导时间依赖项

systemctl enable mongodb-hugepage-fix

如果您希望立即激活更改(在下次启动之前),

systemctl start mongodb-hugepage-fix
systemctl restart mongod

这个方案对于使用Upstart init解决方案而不是systemd的Ubuntu 14.04来说,是不合适的。

1systemd 的修复对于现代的 MongoDB 安装来说非常完美,谢谢你。 - four43

将以下行添加到/etc/rc.local文件的末尾。
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
  echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi

if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
   echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi

这将在您重新启动服务器时运行。


1有关这个的配置文件吗?rc.local不是一个好主意,因为 rc.local 将在系统启动结束时执行。所以 mongodb 服务仍将使用默认设置。 - Feng Yu
2编辑/etc/default/grub文件,修改"GRUB_CMDLINE_LINUX_DEFAULT="transparent_hugepage=never"这一行,并运行update-grub命令,然后重新启动服务器。 - PKumar
2谢谢,它有效。但是,有没有类似的方法来修改/sys/kernel/mm/transparent_hugepage/defrag?当我重新启动时,Mongo shell也会告诉我“**警告:/sys/kernel/mm/transparent_hugepage/defrag是'always'。” - Feng Yu
@FengYu 试试这个页面:https://docs.mongodb.org/manual/tutorial/transparent-huge-pages/ - PKumar

由于我们正在使用Ansible部署机器,我不喜欢修改rc文件。
我尝试使用sysfsutils/sysfs.conf,但在快速(或慢速)机器上启动服务时遇到了时间问题。看起来有时候mongod在sysfsutils之前启动。有时候它工作,有时候不工作。
由于mongod是一个upstart进程,我发现最干净的解决方案是添加文件/etc/mongo_vm_settings.conf,并包含以下内容:
# Ubuntu upstart file at /etc/init/mongod_vm_settings.conf
#
#   This file will set the correct kernel VM settings for MongoDB
#   This file is maintained in Ansible

start on (starting mongod)
script
  echo "never" > /sys/kernel/mm/transparent_hugepage/enabled
  echo "never" > /sys/kernel/mm/transparent_hugepage/defrag
end script

这将在mongod启动之前运行脚本。 重新启动mongod(sudo service mongod restart)即可完成。

请注意,此解决方案使用的是“Upstart”初始化系统,而Ubuntu 16.04基于systemd初始化系统。 - Mark Stosberg

阅读了一些警告日志后,我在/etc/sysfs.conf中添加了这两行代码,然后就完成了。
kernel/mm/transparent_hugepage/enabled = never
kernel/mm/transparent_hugepage/defrag = never

重新应用这些更改后重启机器。

这仍然需要sysfsutils软件包(请参阅我的回答)。 - David Foerster
当然是需要的 - Ulv3r

GRUB在升级后会发生变化,rc.local只有在mongo启动后才会运行,所以也许我们应该在rc.local的末尾添加service mongo restart,就像这样:
如果测试 -f /sys/kernel/mm/transparent_hugepage/enabled存在,则执行以下操作: echo never > /sys/kernel/mm/transparent_hugepage/enabled fi
如果测试 -f /sys/kernel/mm/transparent_hugepage/defrag存在,则执行以下操作: echo never > /sys/kernel/mm/transparent_hugepage/defrag fi
等待1秒钟并且服务mongod重启
或者也许有人成功地将上述行添加到Ubuntu 14.04的init脚本中?