試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

hwmonモジュール+lm_sensorsとhddtempで温度を取得

Linuxカーネルには、センサーチップからの情報を取得するhwmonという仕組みがあり、マザーボードにセンサーチップがあって、かつ、hwmonのセンサードライバの中に、使用しているセンサーチップに対応しているものがあれば*1lm_sensorsというツールを用いて各種温度を取得できる。対応していれば、各種電圧やファン回転数も取得できる。
ハードディスクの温度に関しては、温度取得の経路も方法も異なるため、別のツールhddtempを用いて取得する。

カーネルの設定

ディストリのカーネルではモジュールになっている可能性が高い。カスタムカーネルで、どのドライバを選べばよいのか分からない場合、使用されるモジュールが判明するまでは一通りモジュールとしてビルドし、次回のカーネルビルド以降、使用されていないものをビルドしない(無効にする)ようにするのがよい。

Device Drivers  --->
 <M> Hardware Monitoring support  --->
  <M> ドライバ名
  <M> ドライバ名
  ...
  <M> ドライバ名
  [ ]   Hardware Monitoring Chip debugging messages
 <M> I2C support  --->

lm_sensorsのインストール

ディストリのパッケージになっていることが多い。が、「lm_sensors」か「lm-sensors」かの違いがあったりすることはあるので、どちらなのかをパッケージ名検索しておくとよいかもしれない。Gentoo Linuxでは「lm_sensors」、Debian,Ubuntuでは「lm-sensors」。
Gentoo Linuxの場合、lm_sensorsパッケージをインストール・設定した後に、システム起動時に自動で起動されるように

$ sudo rc-update add lm_sensors default

を実行しておくとよい。後で設定を完了したら

$ sudo /etc/init.d/lm_sensors start

でデーモンを開始する。

lm_sensorsの設定

$ sudo sensors-detect

の後、指示に従ってセンサーチップの検出作業を進めて(よく分からなければEnter連打でもOK)、最後に設定ファイル*2へその設定を書き出すかどうかを質問されるので、「yes」とすれば設定完了。

sensorsコマンドで実験

sensorsコマンドで、取得可能な情報が一通り表示される。実際には他のツール経由で使用されることが多い。
環境により、取得できる情報には違いが出る。

$ sensors
k8temp-pci-00c3
Adapter: PCI adapter
Core0 Temp:
             +45°C
Core1 Temp:
             +45°C

w83627ehf-i2c-9191-a10
 ERROR: Can't get adapter or algorithm?!?
VCore:     +1.00 V  (min =  +0.00 V, max =  +1.74 V)
in1:      +13.46 V  (min =  +2.90 V, max =  +3.64 V) ALARM
AVCC:      +3.30 V  (min =  +1.66 V, max =  +2.96 V) ALARM
3VCC:      +3.30 V  (min =  +3.20 V, max =  +2.77 V) ALARM
in4:       +1.69 V  (min =  +0.26 V, max =  +0.39 V) ALARM
in5:       +1.91 V  (min =  +0.21 V, max =  +0.01 V) ALARM
in6:       +6.12 V  (min =  +1.48 V, max =  +2.97 V) ALARM
VSB:       +3.30 V  (min =  +3.15 V, max =  +2.21 V) ALARM
VBAT:      +3.10 V  (min =  +1.39 V, max =  +2.94 V) ALARM
in9:       +1.58 V  (min =  +0.32 V, max =  +1.36 V) ALARM
Case Fan: 1534 RPM  (min = 14062 RPM, div = 8) ALARM
CPU Fan:     0 RPM  (min = 1318 RPM, div = 128) ALARM
Aux Fan:     0 RPM  (min = 5273 RPM, div = 128) ALARM
fan4:      691 RPM  (min = 2280 RPM, div = 16) ALARM
fan5:        0 RPM  (min = 1171 RPM, div = 128) ALARM
Sys Temp:    +36°C  (high =    -7°C, hyst =  +122°C)
CPU Temp:  +43.0°C  (high = +75.0°C, hyst = +127.0°C)
AUX Temp:  +46.5°C  (high = +80.0°C, hyst = +75.0°C)

表示される項目名と実際の項目は、異なることがある。上の例では、CPUファンが「fan4」になっている。BIOS設定で、CPUの温度に応じてCPUファン回転数を変えるようにしているため、「アイドル時には値が低いが、負荷がかかると2,000を越える」ということから分かる。他には、シングルコアCPUなのに、k8tempで取得している温度の表示で「Core0」「Core1」と表示が分かれていたりもするが、動作上、問題があるわけではない。
(2007/7/28)この表示を実際と合わせたいのであれば、/etc/sensors.confを調整する。手元の環境では

--- /etc/sensors.conf.orig
+++ /etc/sensors.conf
@@ -2635,15 +2635,27 @@
 chip "w83627ehf-*"

     label in0 "VCore"
-    label in2 "AVCC"
-    label in3 "3VCC"
-    label in7 "VSB"
-    label in8 "VBAT"
+    ignore in1
+    ignore in2
+#    label in2 "AVCC"
+#    label in3 "3VCC"
+    ignore in3
+    ignore in4
+    ignore in5
+    ignore in6
+#    label in7 "VSB"
+    ignore in7
+#    label in8 "VBAT"
+    ignore in8
+    ignore in9


 # +12V is in1 and +5V is in6 as recommended by datasheet
-    compute in1 @*(1+(56/10)),  @/(1+(56/10))
-    compute in6 @*(1+(22/10)),  @/(1+(22/10))
+#    compute in1 @*(1+(56/10)),  @/(1+(56/10))
+#    compute in6 @*(1+(22/10)),  @/(1+(22/10))
+    # VCore (1.00V - 1.25V)
+    set in0_min    1.0*0.95
+    set in0_max    1.25*1.05
 #    set in1_min   12.0*0.9
 #    set in1_max   12.0*1.1
 #    set in6_min   5.0*0.95
@@ -2661,23 +2673,23 @@

 # Fans
    label fan1      "Case Fan"
-   label fan2      "CPU Fan"
-   label fan3      "Aux Fan"
-#  ignore fan3
-#  ignore fan4
-#  set fan1_min    1200
-#  set fan2_min    1700
+   ignore fan2
+   ignore fan3
+   label fan4      "CPU Fan"
+   ignore fan5
+  set fan1_min    1000
+  set fan4_min    600

 # Temperatures
    label temp1     "Sys Temp"
-   label temp2     "CPU Temp"
+   ignore temp2
    label temp3     "AUX Temp"

 #  ignore temp3
-#  set temp1_over  45
-#  set temp1_hyst  40
-#  set temp2_over  45
-#  set temp2_hyst  40
+  set temp1_over  50
+  set temp1_hyst  45
+  set temp3_over  55
+  set temp3_hyst  50


 # Fintek F71805F/FG configuration
@@ -2807,7 +2819,7 @@

 chip "k8temp-*"

-   label temp1 "Core0 Temp"
-   label temp2 "Core0 Temp"
-   label temp3 "Core1 Temp"
-   label temp4 "Core1 Temp"
+   label temp1 "CPU Temp"
+   ignore temp2
+   ignore temp3
+   ignore temp4

と修正することで

$ sensors
k8temp-pci-00c3
Adapter: PCI adapter
CPU Temp:    +45°C

w83627ehf-i2c-9191-a10
 ERROR: Can't get adapter or algorithm?!?
VCore:     +0.97 V  (min =  +0.95 V, max =  +1.31 V)
Case Fan: 1480 RPM  (min = 1004 RPM, div = 8)
CPU Fan:   697 RPM  (min =  602 RPM, div = 16)
Sys Temp:    +37°C  (high =   +50°C, hyst =   +45°C)
AUX Temp:  +45.5°C  (high = +55.0°C, hyst = +50.0°C)

のようになった。不要な項目は「ignore」指定をしておくと、後述のGKrellMで設定するときにも楽。チップごとにセクション分けされているので、使用しているチップ名に応じたセクション(手元では「chip "w83627ehf-*"」)を編集する。また、各種データ範囲も設定し、k8tempのシングルコアCPUでの表示も1つにしている。
(w83627ehfでの)電圧に関しては、3.3Vは正常に値が出ているのだが、/etc/sensors.confでの計算(上の差分の中にもその部分が見える)がおかしいのか、in1とin6は、12Vと5Vとは程遠い値*3BIOS上の表示では、きちんと合っている。しかし、どういう計算をすれば手元のマザーボードに合うのかが分からないので、ignoreにしてしまった。

ハードディスクの温度を取得(hddtemp)

ハードディスクの温度を(「S.M.A.R.T.」経由で)取得するhddtempもディストリのパッケージになっていることが多い。デーモン動作させると、

$ nc 127.0.0.1 7634

で一般ユーザでも温度が取得できる*4Gentoo Linuxでは

$ sudo rc-update add hddtemp default

自動起動させるようにする。インストール後、手動でデーモンを開始させるには

$ sudo /etc/init.d/hddtemp start

を実行。

GKrellMで各種情報を表示させる

GKrellMの温度表示機能がlm_sensorshddtempに対応しているため、常に温度を監視することができる。センサの設定からチェックを入れるだけなので簡単。ファン回転数と電圧も、対応しているものに関しては表示できる。

hwmonのデータをカーネル(/sys/bus/ 以下)から直接取る(cactiで使用中の取得方法)

最も動作の軽い表示方法ではあるのだが、見つかった項目(temp1_inputなど)が、ハードウェア上のどこの値なのかをしっかりと把握しておく必要がある。また、格納されている値そのままの形では使用できず、多少の加工作業が必要なものも多い。
この取得方法は、cactiでグラフを作りたいときに役に立つかもしれない。しかし、例を書いても、データのパス名(/sys/bus/i2c/devices/9191-0a10/fan4_inputなど)が環境によって異なるため、参考にはならないかもしれない。対応関係は、sensorsコマンドの出力結果と照らし合わせるのもよい。
以下、cactiでデータ取得に使用しているスクリプトをそのまま貼り付ける。/bin/dashは綴りミスではなく、dashという軽いシェルを使うよう指定している。

#! /bin/dash
cputempsrc=/sys/bus/pci/drivers/k8temp/0000:00:18.3/temp1_input
systempsrc=/sys/bus/i2c/devices/9191-0a10/temp1_input
cpufansrc=/sys/bus/i2c/devices/9191-0a10/fan4_input
vcoresrc=/sys/bus/i2c/devices/9191-0a10/in0_input
cputemp=$(cut -c 1-2 $cputempsrc).$(cut -c 3- $cputempsrc | sed -e s/00$//)
systemp=$(cut -c 1-2 $systempsrc).$(cut -c 3- $systempsrc | sed -e s/00$//)
vcore=$(printf %04d $(cat $vcoresrc) | cut -c 1).$(printf %04d $(cat $vcoresrc) | cut -c 2-)
printf "CPUTemp:$cputemp SYSTemp:$systemp CPUFan:$(cat $cpufansrc) CPUVCore:$vcore"

(2007/10/23)Linux 2.6.23からは、直接/sys/以下から取る場合の場所が一部変更されたようだ。

#! /bin/dash
cputempsrc=/sys/bus/pci/drivers/k8temp/0000:00:18.3/temp1_input
systempsrc=/sys/devices/platform/w83627ehf.2576/temp1_input
cpufansrc=/sys/devices/platform/w83627ehf.2576/fan4_input
vcoresrc=/sys/devices/platform/w83627ehf.2576/in0_input
cputemp=$(cut -c 1-2 $cputempsrc).$(cut -c 3- $cputempsrc | sed -e s/00$//)
systemp=$(cut -c 1-2 $systempsrc).$(cut -c 3- $systempsrc | sed -e s/00$//)
vcore=$(printf %04d $(cat $vcoresrc) | cut -c 1).$(printf %04d $(cat $vcoresrc) | cut -c 2-)
printf "CPUTemp:$cputemp SYSTemp:$systemp CPUFan:$(cat $cpufansrc) CPUVCore:$vcore"

のようにすることで値が取れている。


その他、cacti用の(hwmonと無関係な)データ収集スクリプトを貼っておく。
CPUのクロック(cpufrequtilscpufreq-infoを使用)

#! /bin/dash
printf $(cpufreq-info -f) | sed -e s/000$//

NVIDIA GPUの温度(nvidia-settingsで取得できる場合)

#! /bin/dash
nvidia-settings -q GPUCoreTemp | grep Attr | awk '{printf $4}' | sed -e s/\.$//

NVIDIA GPUの温度(nvidia-settingsでは取れないが、nvclockでは取れる場合・若干処理が重め)

#! /bin/dash
nvclock -T | tail -n 1 | awk '{printf $4}' | sed -e s/C//

cactiの中での使い方としては、

  1. 「Data Input Methods」を作成し、「Script/Command」という種類で設定、各スクリプトの場所(パス名)を書いて使う
  2. 「Data Templates」を作成し、複数のフィールドを持っているものは、「Data Source Item」をそれぞれ設定(結構面倒)
  3. 対応したデータテンプレートを指定して「Data Sources」を作成
  4. 「Graph Templates」でグラフテンプレートを作る(結構面倒)
  5. 対応したグラフテンプレートを指定して「Graph Management」で実際のグラフを作成

という流れ。cactiは準備も設定も面倒で、仕組みも作業手順も難しい。
http://www.aconus.com/~oyaji/suse9.3/cacti_linux2.htm
が大変参考になっている。詳しい設定方法はそちらを参照。

cacti以外では、同様の要領で、GNU screen表示させることもできる。

*1:自動検出・自動設定してくれるため、手間はかからない

*2:ディストリに適したファイルに書いてくれるようになっている

*3:元々の値を試しに取ってみたところ、in1が2040、in6が1912で、/etc/sensors.confでの計算(compute)の結果が初めのsensorsの結果になっていることを確認

*4:ポート番号は設定で変更可能