nosforever nosforever - 1 year ago 60
Linux Question

Using SED to convert sensors command output to a loggable entry

Consider the following

command output:

temp1: +67.0°C crit = +0.0°C, hyst = +0.0°C

temp1: +59.0°C crit = +0.0°C, hyst = +0.0°C

temp1: +64.0°C crit = +0.0°C, hyst = +0.0°C

Vbat: +3.43 V
temp1: +43.0°C low = +97.0°C, high = -90.0°C ALARM sensor = thermistor
temp2: +40.0°C low = +79.0°C, high = +2.0°C ALARM sensor = thermistor
temp3: -128.0°C low = -128.0°C, high = +69.0°C sensor = disabled

temp1: +25.1°C high = +70.0°C
crit = +90.0°C, hyst = +87.0°C

power1: 13.04 W crit = 94.99 W

cpu_fan: 0 RPM

I'm trying to turn this into a log entry, like this, where the "temp1" values are placed next to the PCI adapters, and the board (it8721-isa-0290):

<Date_Time> amdgpu-pci-0100 - +67.0°C | amdgpu-pci-0600 - +59.0°C | amdgpu-pci-0700 - +64.0°C | it8721-isa-0290 - +43.0°C

I think sed is the correct tool for this, but if it's not please let me know. I have already trimmed some data out using 2 sed commands, but I am not quite sure how to either delete out the rest that I don't need or match on just the stuff I do need. Some assistance would be greatly appreciated.

EDIT: Here's what I have so far as far as a command:

sensors | sed -e '/Adapter/d' -e '/in/d' -e 's/[)(]//g' -e '/Vbat/d' \
`-e 's/crit.*//' -e 's/low.*//' -e '/temp2/d' -e '/temp3/d' -e '/^k10temp-pci-`00c3$/,$d' \
-e 's/temp.://'

Here's the output (just need to add some separators):

amdgpu-pci-0100 +68.0°C amdgpu-pci-0600 +60.0°C amdgpu-pci-0700 +65.0°C it8721-isa-0290 +44.0°C

Is there an easier way to accomplish what I did?

Answer Source

The output of the sensors command heavily depends on the configuration file. For example, it is possible to rename the labels with a configuration similar to the following:

chip "as99127f-*"
  label temp1 "Mobo Temp"
  label temp2 "CPU0 Temp"

With such configuration the output of sensors command will look like this:

Mobo Temp:        +35.0°C  (high =  +0.0°C, hyst = -128.0°C)
CPU0 Temp:        +47.5°C  (high = +100.0°C, hyst = +75.0°C)

However, the sensors utility provides -u switch that prints an easy-to-parse raw data. In raw mode, the chip feature names are printed in standard formats such as temp1_input, temp1_max, temp1_crit, and temp1_crit_alarm, e.g.:

Adapter: Virtual device
  temp1_input: 64.000
  temp1_crit: 120.000
  temp2_input: 30.000
  temp2_crit: 120.000

Adapter: ISA adapter
Physical id 0:
  temp1_input: 67.000
  temp1_max: 87.000
  temp1_crit: 105.000
  temp1_crit_alarm: 0.000
Core 0:
  temp2_input: 67.000
  temp2_max: 87.000
  temp2_crit: 105.000
  temp2_crit_alarm: 0.000

The format is still not as easy to parse as it could be (think of JSON, or XML). The chip feature blocks are separated with newlines. Each block starts with the chip name. So you need to remember when the block starts, and print when the block ends (an empty line, or end of file).

It is possible to implement the algorithm in AWK. It is even possible to do this in SED. But I find these tools inconvenient for this case. I would rather use more flexible tool such as Perl (maybe I have just used to Perl more than to AWK).


my $nl = 0;
my $chip;
my @t;

while (<>) {
  if ($chip eq "" or $nl) {
    ($chip = $_) =~ s/\n*$//;
    @t = ()
  } elsif ($_ =~ /temp\d+_input: ([\d\.]+)/m) {
     push @t, $1;

  $nl = $_ eq "\n";

  # Average chip's temperature
  if ($nl or eof()) {
    my $t; map { $t += $_ } @t;
    printf("%s - %.1f°C\n", $chip, $t / (scalar @t))


sensors -u | perl

Sample Output

acpitz-virtual-0 - 47.5°C
coretemp-isa-0000 - 65.4°C

The script calculates average temperature for the temp\d+_input entries. You can easily change the script to fit our needs. For example, in order to print a list of all "input" temperatures for a chip, replace the last block in the loop with the following:

printf("%s - %s°C\n", $chip, join("|", map { sprintf("%.1f", $_) } @t))
  if $nl or eof();

Sample Output

acpitz-virtual-0 - 67.0|30.0°C
coretemp-isa-0000 - 68.0|67.0|63.0|66.0|61.0°C


The code in the samples prints newlines for each chip for the sake of clarity. Replace the newlines (\n) with " | ", or whatever you find suitable for your case.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download