Background
I’m using Conky for monitoring the system. After a system upgrade, the CPU temperatures were gone. Conky’s standard error showed the following.
Conky: can't open '/sys/class/hwmon/hwmon0/temp3_input': No such file or
directory please check your device or remove this var from Conky...
Source of message: https://bbs.archlinux.org/viewtopic.php?id=82231
An easy fix would be to adjust the following lines in .conkyrc
according to
the number N
in /sys/class/hwmon/hwmonN
containing the file temp3_input
.
(You may adjust the number 3
according to the number of CPU of your device.)
The number of CPU can be found using grep -c ^processor /proc/cpuinfo
.
CPU 1: ${hwmon 0 temp 1}°C ${cpu cpu1}% ${alignr} CPU 2: ${hwmon 0 temp 2}°C ${cpu cpu2}%
${cpugraph cpu1 60,120} ${alignr} ${cpugraph cpu2 60,120}
To find out what the above paths represent, issue tree /sys/class/hwmon
$ tree /sys/class/hwmon/
/sys/class/hwmon/
├── hwmon0 -> ../../devices/virtual/hwmon/hwmon0
├── hwmon1 -> ../../devices/platform/coretemp.0/hwmon/hwmon1
└── hwmon2 -> ../../devices/pci0000:00/0000:00:1c.0/0000:01:00.0/hwmon/hwmon2
3 directories, 0 files
coretemp.0
represents the CPU temperatures. It’s linked to hwmon1
, so for
the current session, the right config should be ${hwmon 1 temp m}
. However,
as written in the linked forum message, after a system upgrade, the digit would
shift.
Problem
How to configure Conky properly so that the CPU temperatures will be shown
despite the shifting of temp3_input
’s path?
Difficulty
Start with a simple idea.
-
Test the existence of
temp3_input
for directorieshwmonN
, whereN = 0,...,3
. Only oneN
would give positive result. Assign this to some variable${myvar}
.for (( i=0; i<3; i++ )); do test -e /sys/class/hwmon/hwmon$i/temp3_crit && echo $i || echo -n done # returns `1`
Wrap this shell command with
${exec ...}
in.conkyrc
. -
Write something like
${hwmon ${myvar} temp m}
form = 1,...
in.conkyrc
.
This leads us to a deadend. The syntax in item 2 doesn’t
work. One has to use a Conky Lua script to make things work.
Note that the .conkyrc
syntax has changed so significantly that the TEXT
section has been replaced by a conky.text = [[ ... ]]
block. It
took me an hour to find the right wiki page. This line in
.conkyrc
inside conky.config = { ... }
calls the Lua script.
lua_load = '/home/username/scripts/script.lua'
I’m not sure whether relative path is allowed. You may test and let me know in the comments below.
Since I don’t know Lua, my script won’t be as fancy as the official sample. It took me some time to learn these basics in Conky Lua scripts.
- All Lua functions directly called from
.conkyrc
with the syntax${lua myfct[ params]}
has to be written asfunction conky_myfct ([parmas])
in the Lua script file. The examples that I’ve seen use${lua conky_myfct}
, but skippingconky_
in the previous expression still gives me the desired result, as you can see from the animated screenshot below. - The arguments for functions in
${lua myfct args}
in.conkyrc
don’t need to be surrounded by parenthesis()
, contrarily to the Conky Lua scriptmyfct(args)
. - Any function directly called by
.conkyrc
has to return a string. Other return types are discarded. Usetostring()
to convert other data types to strings. - Multiple argument in
print("arg1", var2, "arg3")
is possible, but the output string will be delimited by tabs by default. That’s not desirable in some cases. - The syntax for string concatenation is
..
. Subtraction-
has a higher precedence than string concatenation..
, so quantities liken-1
has to be enclosed with a pair of parenthesis()
when used with..
. conky_parse("${...}")
returns a string.
Solution
The actual Conky Lua script will be divided into three stages for the ease of maintenance.
-
Verify whether
file_exists
by its filename
.function file_exists(name) local f=io.open(name,"r") if f~=nil then io.close(f) return true else return false end end
-
Find the right
N
so that/sys/class/hwmon/hwmonN/temp3_crit
exists.function findHwmonNum() for i = 0,10,1 do if file_exists("/sys/class/hwmon/hwmon"..i.."/temp3_crit") then return i end end end
-
To replace
${hwmon N temp n}
with the function${lua cputemp n}
in.conkyrc
, we need to read Conky’s string output withconky_parse(${...})
. The string inside is the concatenation of${hwmon
,findHwmonNum()
(representingN
in the previous section),temp
,n
(the input argument) and}
. I’ve hard-codedCPU 1
, …,CPU 3
in.conkyrc
because of the alignment of CPU info. I would like to keep the code maintainable with my basic knowledge in Lua. This gives the following function.function conky_cputemp(n) return conky_parse("${hwmon "..findHwmonNum().." temp "..n.."}") end