PID fan controller Perl script

Joined
Jan 27, 2020
Messages
577
Here's how to get the PID fan controller Perl script on TrueNAS SCALE. I started with this script and had it running for years on freeNAS then TrueNAS Core. I originally had it for SATA drives, then moved to SAS and had to customize it for the output of those so I can start tracking the SAS temps. Moving to SCALE was... interesting as all stopped working. Hello there, Linux. :wink: I had to further customize mine to fit my setup as I discovered camcontrol is gone and so is sysctl. Joy. But, in the end, it turned out quite okay and the changes were minimal. I keep my folder with the fan controller in /root/nas_fan_control-master and start it in SCALE with the command (in GUI it is command not script): bash /root/start_fan_controller, which a single-liner to start the pl file and log it.
Code:
#!/bin/bash
echo "Starting Fan Controller..."
/root/nas_fan_control-master/PID_fan_control.pl &>> /root/nas_fan_control-master/PID_fan_control.log &

The only changes required when moving from FreeBSD to Linux were:
1. perl, ipmitool locations:
from
Code:
$ipmitool = "/usr/local/bin/ipmitool";
to
Code:
$ipmitool = "/usr/bin/ipmitool";
Look through your script's files for /usr/local/bin and remove the /local so it becomes /usr/bin/whatever

2. With camcontrol gone I switched to lsblk:
from
Code:
$disk_list = `camcontrol devlist | grep -v "SSD" | grep -v "Verbatim" | grep -v "Kingston" | grep -v "Elements" | sed 's:.*(::;s:).*::;s:,pass[0-9]*::;s:pass[0-9]*,::' | egrep '^[a]*da[0-9]+\$' | tr '\012' ' '`;
to
Code:
$disk_list = `lsblk -d -n -o model,name | grep -v "SSD" | grep -v "Verbatim" | grep -v "Kingston" | grep -v "Elements" | sed 's:YOURDRIVEMODEL  .::;' | tr '\012' ' '`;
All I did was ssh into my SCALE, then ran lsblk -d -n -o model,name, that pulled up drive model and identifier. Then I started grepping what I did not need (the SSD) and then I amended the sed part to remove my model till all I had left was the name of the drives, in my cases those were sda through sdk (sdl was the ssd so it was grep -v for it).

3. Another example of a small tweak (grep and vals of note here). Sorry, did not bother to change the comments:
from
Code:
    foreach my $item (@hd_list)
    {
        my $disk_dev = "/dev/$item";
        my $command = "/usr/local/sbin/smartctl -A $disk_dev | grep Temperature_Celsius";

        my $output = `$command`;

        my @vals = split(" ", $output);

        # grab 10th item from the output, which is the hard drive temperature (on Seagate NAS HDs)
        my $temp = "$vals[9]";
        chomp $temp;
to
Code:
    foreach my $item (@hd_list)
    {
        my $disk_dev = "/dev/$item";
        my $command = `/usr/sbin/smartctl -A $disk_dev | grep "Current Drive Temperature"`;

        my $output = $command;

        my @vals = split(" ", $output);

        # grab 10th item from the output, which is the hard drive temperature (on Seagate NAS HDs)
        my $temp = "$vals[3]";
        chomp $temp;

3. With sysctl gone I switched to sensors for cpu temp reading since it came preinstalled on SCALE:
from
Code:
    my $core_temps = `sysctl -a dev.cpu | egrep -E \"dev.cpu\.[0-9]+\.temperature\" | awk '{print \$2}' | sed 's/.\$//'`;
to
Code:
    my $core_temps = `sensors | egrep -E \"Core [0-9]+\" | awk '{print \$3}' | tr -d '+' | sed 's/.0°C//'`;
    chomp($core_temps);


Of course it will greatly depend on your disk types and cpus you use: Intel/AMD, SATA vs SAS etc. I cannot stress this enough: use the awesome debug! Get it to 4 and a lot will become obvious. It's a lot of:
1. ps aux | grep -i PID_fan_control
2. kill -9 thePIDfromAbove
3. Upload via filezilla the new .pl file
4. Delete the old log files (otherwise the incorrectly logged values for disks you do NOT need will still show up in your .log and mess up your view - will make your values out of order/misplaced/skewed).
5. Start the script.
6. Wait for initial spin up and for all to quiet down (about 30s-45s)
7. Pull logs (debug and normal), inspect, make .pl corrections. Rinse and repeat.

Here's the output from my working setup after the changes I made. As you can tell from the timestamps... I just got it working:tongue::
Code:
PID Fan Controller Log  ---  Target 6 Disk HD Temperature = 39.00 deg C  ---  PID Control Gains: Kp =  5.333, Ki =  0.000, Kd =  48.0
                                                                  Max   Ave  Temp   Fan   Fan  Fan %   CPU    P      I      D      Fan
2023-01-14 sda  sdb  sdc  sdd  sde  sdf  sdg  sdh  sdi  sdj  sdk Temp  Temp   Err  Mode   RPM Old/New Temp  Corr   Corr   Corr    Duty
19:11:12   36   36   36   36   37   38   37   38   36   39   38  ^39  37.83 -1.17  Full  2800  30/21   41  -9.33  -0.00    0.00   20.67%
19:12:43   36   36   34   36   37   38   37   38   34   39   38  ^39  37.83 -1.17  Full  2300  21/11   40  -9.33  -0.00    0.00   11.33%
19:14:13   36   36   36   36   37   38   37   38   36   39   38  ^39  37.83 -1.17  Full  2200  11/10   41  -9.33  -0.00    0.00   10.00%
19:15:42   36   37   36   36   37   38   38   38   36   39   39  ^39  38.17 -0.83  Full  2400  10/14   40  -6.67  -0.00   10.67   14.00%
19:17:13   36   37   36   37   37   38   38   38   36   39   38  ^39  38.00 -1.00  Full  2200  14/10   42  -8.00  -0.00   -5.33   10.00%
19:18:42   36   37   36   37   37   38   38   38   36   39   39  ^39  38.17 -0.83  Full  2200  10/10   40  -6.67  -0.00    5.33   10.00%
19:20:13   36   37   36   37   37   38   38   38   36   39   39  ^39  38.17 -0.83  Full  2200  10/10   41  -6.67  -0.00    0.00   10.00%
19:21:43   36   37   36   37   37   39   38   39   36   39   39  ^39  38.50 -0.50  Full  2500  10/17   41  -4.00  -0.00   10.67   16.67%
19:23:13   36   37   36   37   37   39   38   38   36   39   39  ^39  38.33 -0.67  Full  2200  17/10   41  -5.33  -0.00   -5.33   10.00%
19:24:43   36   37   36   37   37   39   38   39   36   39   39  ^39  38.50 -0.50  Full  2200  10/11   43  -4.00  -0.00    5.33   11.33%
19:26:12   36   37   36   37   37   39   38   39   36   39   39  ^39  38.50 -0.50  Full  2200  11/10   41  -4.00  -0.00    0.00   10.00%
19:27:43   37   37   37   37   37   39   38   39   36   39   39  ^39  38.50 -0.50  Full  2200  10/10   42  -4.00  -0.00    0.00   10.00%
19:29:12   37   37   36   37   38   39   38   39   37   39   39  ^39  38.67 -0.33  Full  2300  10/13   41  -2.67   0.00    5.33   12.67%
19:30:43   37   38   37   37   38   39   38   39   37   39   39  ^39  38.67 -0.33  Full  2200  13/10   41  -2.67  -0.00    0.00   10.00%
19:32:13   37   38   37   37   38   39   38   39   37   39   39  ^39  38.67 -0.33  Full  2200  10/10   42  -2.67  -0.00    0.00   10.00%
19:33:42   37   38   37   37   38   39   38   39   37   39   39  ^39  38.67 -0.33  Full  2200  10/10   42  -2.67  -0.00    0.00   10.00%


PID Fan Controller Log  ---  Target 6 Disk HD Temperature = 39.00 deg C  ---  PID Control Gains: Kp =  5.333, Ki =  0.000, Kd =  48.0
                                                                  Max   Ave  Temp   Fan   Fan  Fan %   CPU    P      I      D      Fan
2023-01-14 sda  sdb  sdc  sdd  sde  sdf  sdg  sdh  sdi  sdj  sdk Temp  Temp   Err  Mode   RPM Old/New Temp  Corr   Corr   Corr    Duty
19:36:09   37   38   37   38   38   39   38   39   37   39   39  ^39  38.67 -0.33  Full  3100  30/27   42  -2.67  -0.00    0.00   27.33%


Hope this helps someone. My respect to the creator(s) of the script for their amazing work.
Would be very neat of you if you could share your complete script either here as attachment - or even better - as a git(hub). So everybody can join in to further improve this.
Thanks!
 
Joined
Jan 27, 2020
Messages
577
3. Another example of a small tweak (grep and vals of note here). Sorry, did not bother to change the comments:
from
Code:
    foreach my $item (@hd_list)
    {
        my $disk_dev = "/dev/$item";
        my $command = "/usr/local/sbin/smartctl -A $disk_dev | grep Temperature_Celsius";

        my $output = `$command`;

        my @vals = split(" ", $output);

        # grab 10th item from the output, which is the hard drive temperature (on Seagate NAS HDs)
        my $temp = "$vals[9]";
        chomp $temp;
to
Code:
    foreach my $item (@hd_list)
    {
        my $disk_dev = "/dev/$item";
        my $command = `/usr/sbin/smartctl -A $disk_dev | grep "Current Drive Temperature"`;

        my $output = $command;

        my @vals = split(" ", $output);

        # grab 10th item from the output, which is the hard drive temperature (on Seagate NAS HDs)
        my $temp = "$vals[3]";
        chomp $temp;
This is confusing to me. smartctl -A reports "Temperature_Celsius" and not "Current Drive Temperature". Also the referencing val position 3 is text as to the original script the position was 9, which represents the drive temp value. So is it a variation of SMART data reporting or why is it different from my smartctl -A on SCALE?
 

awasb

Patron
Joined
Jan 11, 2021
Messages
403
Just in case someone is asking: Yes! With a Supermicro a2sdi-board (AST2400 BMC v.3.95) the script works without any further adjustments or hacks. (The usual config aside.) Many thanks!
 
Top