{"id":5414,"date":"2026-08-30T18:40:36","date_gmt":"2026-08-30T09:40:36","guid":{"rendered":"https:\/\/donguri3.net\/server-tech\/linux-server-fan-control-guide-2\/"},"modified":"2026-08-30T18:40:38","modified_gmt":"2026-08-30T09:40:38","slug":"linux-server-fan-control-guide","status":"publish","type":"post","link":"https:\/\/donguri3.net\/en\/server-tech\/linux-server-network\/linux-server-fan-control-guide\/","title":{"rendered":"Fan Control on Linux Servers"},"content":{"rendered":"<p>In a home server running 24\/7, the cooling fan is typically the component most prone to wear and tear, and where issues tend to surface most visibly. Due to long-term operation, you may suddenly experience severe abnormal noise from the fan caused by a misaligned shaft or bearing degradation. For compact servers such as the one built in our previous article, &#8220;<a href=\"https:\/\/donguri3.net\/server-tech\/asrock-beebox-pt3-mini-pc-server\/\">Introduction to a Mini PC Recording Server Built with ASRock Beebox + PT3<\/a>&#8220;, higher fan rotation speeds further amplify this noise. While replacing the physical part is clearly the ultimate solution, arranging replacement parts usually takes a few days. Therefore, as an immediate stopgap measure until the replacement arrives, we can implement a method to control fan behavior directly from the Linux side and minimize unpleasant noise.<\/p>\n<h2>Buying Time Until Hardware Replacement Through Technology<\/h2>\n<p>The purpose of this article is to use standard Linux (such as CentOS 7) toolsets to directly intervene with the hardware monitoring chip on the motherboard and manipulate fan speeds. By redefining a flexible fan curve on the OS side\u2014independent of BIOS or UEFI settings\u2014it becomes possible to avoid specific rotation ranges where abnormal noise occurs, or to completely stop the fan under low loads. The goal is to cover physical failures with software hacks, achieving both the continuation of system operation and a quiet living environment.<\/p>\n<h2>Defining the Balance Between Silence and Cooling<\/h2>\n<p>As a concrete control target, we set the fan output to a PWM value of 0 (complete stop) during idle times when the CPU temperature is relatively low. This reduces physical noise in regular use ranges to zero. On the other hand, to prevent thermal runaway as temperatures rise, we maintain a failsafe that forcibly cools the system at maximum output if the CPU temperature exceeds 70\u00b0C. Rather than simply silencing the noise, the goal of this interim measure is to draw a clear boundary between &#8220;stationary&#8221; and &#8220;cooling&#8221; based on thermometer readings.<\/p>\n<h2>The Barrier of Automatic Control and Identifying Control Ports<\/h2>\n<p>When attempting fan control in a Linux environment, the biggest challenges are &#8220;identifying the target for control&#8221; and &#8220;the intervention of hardware-based automatic control.&#8221; On many motherboards, the chipset independently manages fan speeds and ignores casual write attempts from the OS. Additionally, because multiple devices and PWM ports exist under \/sys\/class\/hwmon\/, you need to track down which port is actually wired to the physical fan. Getting this wrong risks failing to cool areas that need it, causing fatal damage to the system.<\/p>\n<h2>Reconstructing the Fan Curve Using lm_sensors and sysfs<\/h2>\n<p>Below is the procedure for solving these issues and implementing fan control in a general-purpose Linux environment.<\/p>\n<h3>Installing and Scanning with lm_sensors<\/h3>\n<p>First, install the standard package used to retrieve and manipulate temperature and fan speeds.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">yum install -y lm_sensors<\/pre>\n<p>After installation, identify the sensor chips on the motherboard using the following command.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">sensors-detect<\/pre>\n<p>Answer &#8220;YES&#8221; to all prompts and save the configuration at the end to allow the kernel to recognize each sensor.<\/p>\n<h3>Identifying Control Ports and Changing Modes<\/h3>\n<p>In many environments, hardware-based automatic control is enabled by default. Check the status of each port with the following command.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">cat \/sys\/class\/hwmon\/hwmon1\/pwm&#x5B;1-5]_enable<\/pre>\n<p>If the value is 5 (such as Smart Fan mode), manual operations will not be accepted. Write 1 to all ports to switch them to manual mode.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">echo 1 &gt; \/sys\/class\/hwmon\/hwmon1\/pwm1_enable\necho 1 &gt; \/sys\/class\/hwmon\/hwmon1\/pwm2_enable\necho 1 &gt; \/sys\/class\/hwmon\/hwmon1\/pwm3_enable\necho 1 &gt; \/sys\/class\/hwmon\/hwmon1\/pwm4_enable\necho 1 &gt; \/sys\/class\/hwmon\/hwmon1\/pwm5_enable<\/pre>\n<h3>Identifying the Target Fan (Live Verification)<\/h3>\n<p>In some cases, it may be unclear which PWM port is connected to the physical fan. Run the following commands in sequence to find the port where the fan stops (the noise disappears).<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">echo 0 &gt; \/sys\/class\/hwmon\/hwmon1\/pwm1\n# ...\necho 0 &gt; \/sys\/class\/hwmon\/hwmon1\/pwm5<\/pre>\n<p>In our testing, the abnormal noise vanished the moment 0 was written to pwm2, allowing us to identify pwm2 as the control target. Be sure to return the other PWMXs to their original modes.<\/p>\n<h3>Analyzing the Default Fan Curve<\/h3>\n<p>Before changing settings, check the default control points (auto_point) held by the chipset. In our test environment, the following values were configured.<\/p>\n<table data-path-to-node=\"32\">\n<thead>\n<tr>\n<td><strong>Control Point<\/strong><\/td>\n<td><strong>Temperature Threshold (temp)<\/strong><\/td>\n<td><strong>Output Value (PWM)<\/strong><\/td>\n<td><strong>Status Guide<\/strong><\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><span data-path-to-node=\"32,1,0,0\">Point 1<\/span><\/td>\n<td><span data-path-to-node=\"32,1,1,0\">50,000 (50\u00b0C)<\/span><\/td>\n<td><span data-path-to-node=\"32,1,2,0\">0<\/span><\/td>\n<td><span data-path-to-node=\"32,1,3,0\">Stopped<\/span><\/td>\n<\/tr>\n<tr>\n<td><span data-path-to-node=\"32,2,0,0\"><b data-path-to-node=\"32,2,0,0\" data-index-in-node=\"0\">Point 2<\/b><\/span><\/td>\n<td><span data-path-to-node=\"32,2,1,0\"><b data-path-to-node=\"32,2,1,0\" data-index-in-node=\"0\">55,000 (55\u00b0C)<\/b><\/span><\/td>\n<td><span data-path-to-node=\"32,2,2,0\"><b data-path-to-node=\"32,2,2,0\" data-index-in-node=\"0\">76<\/b><\/span><\/td>\n<td><span data-path-to-node=\"32,2,3,0\"><b data-path-to-node=\"32,2,3,0\" data-index-in-node=\"0\">Low-speed rotation (noise occurs)<\/b><\/span><\/td>\n<\/tr>\n<tr>\n<td><span data-path-to-node=\"32,3,0,0\"><b data-path-to-node=\"32,3,0,0\" data-index-in-node=\"0\">Point 3<\/b><\/span><\/td>\n<td><span data-path-to-node=\"32,3,1,0\"><b data-path-to-node=\"32,3,1,0\" data-index-in-node=\"0\">65,000 (65\u00b0C)<\/b><\/span><\/td>\n<td><span data-path-to-node=\"32,3,2,0\"><b data-path-to-node=\"32,3,2,0\" data-index-in-node=\"0\">204<\/b><\/span><\/td>\n<td><span data-path-to-node=\"32,3,3,0\"><b data-path-to-node=\"32,3,3,0\" data-index-in-node=\"0\">Medium-speed rotation (noise occurs)<\/b><\/span><\/td>\n<\/tr>\n<tr>\n<td><span data-path-to-node=\"32,4,0,0\">Point 4<\/span><\/td>\n<td><span data-path-to-node=\"32,4,1,0\">70,000 (70\u00b0C)<\/span><\/td>\n<td><span data-path-to-node=\"32,4,2,0\">229<\/span><\/td>\n<td><span data-path-to-node=\"32,4,3,0\">High-speed rotation<\/span><\/td>\n<\/tr>\n<tr>\n<td><span data-path-to-node=\"32,5,0,0\">Point 5<\/span><\/td>\n<td><span data-path-to-node=\"32,5,1,0\">73,000 (73\u00b0C)<\/span><\/td>\n<td><span data-path-to-node=\"32,5,2,0\">255<\/span><\/td>\n<td><span data-path-to-node=\"32,5,3,0\">Maximum rotation<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Rewriting the Fan Curve (auto_point)<\/h3>\n<pre>To suppress abnormal noise, set the output of points corresponding to regular use ranges (e.g., 55\u00b0C to 65\u00b0C) to \"0\".<\/pre>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\"># Stop the fan at the 55\u00b0C and 65\u00b0C points\necho 0 &gt; \/sys\/class\/hwmon\/hwmon1\/pwm2_auto_point2_pwm\necho 0 &gt; \/sys\/class\/hwmon\/hwmon1\/pwm2_auto_point3_pwm<\/pre>\n<p>This allows you to logically create a &#8220;semi-fanless&#8221; state where the fan only spins under high load.<\/p>\n<h2>Conclusion<\/h2>\n<p>While the golden rule of maintenance is to &#8220;promptly replace broken parts,&#8221; Linux&#8217;s powerful control mechanisms provide a clear answer to how to comfortably get through downtime until replacement, or how to eliminate unnecessary noise during low-load periods. The direct manipulation through the sysfs interface introduced here is a versatile hack applicable not only to compact servers like the BeeBox, but also to many Linux systems. Supplementing physical limitations with logical operations and tailoring tools to suit your exact needs\u2014this is precisely the kind of enjoyment found at the intersection of &#8220;craftsmanship and technology&#8221; cherished here at Nando Kobo.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In a home server running 24\/7, the cooling fan is typically the component most prone to wear and tear, and whe [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":3042,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_locale":"en_US","_original_post":"https:\/\/donguri3.net\/?p=3039","footnotes":""},"categories":[1170],"tags":[105,10,275,341,331],"class_list":["post-5414","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux-server-network","tag-linux","tag-server","tag-275","tag-341","tag-331","en-US"],"_links":{"self":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/5414","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/comments?post=5414"}],"version-history":[{"count":1,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/5414\/revisions"}],"predecessor-version":[{"id":5417,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/5414\/revisions\/5417"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/media\/3042"}],"wp:attachment":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/media?parent=5414"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/categories?post=5414"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/tags?post=5414"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}