Рассмотрим следующий вывод команды sensor:

amdgpu-pci-0100
temp1:        +67.0°C  crit =  +0.0°C, hyst =  +0.0°C

amdgpu-pci-0600
temp1:        +59.0°C  crit =  +0.0°C, hyst =  +0.0°C

amdgpu-pci-0700
temp1:        +64.0°C  crit =  +0.0°C, hyst =  +0.0°C

it8721-isa-0290
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

k10temp-pci-00c3
temp1:        +25.1°C  high = +70.0°C
                       crit = +90.0°C, hyst = +87.0°C

fam15h_power-pci-00c4
power1:       13.04 W  crit =  94.99 W

asus-isa-0000
cpu_fan:        0 RPM

Я пытаюсь превратить это в запись журнала, например, где значения «temp1» помещаются рядом с адаптерами PCI и платой (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

Я думаю, что sed - правильный инструмент для этого, но если это не так, дайте мне знать. Я уже обрезал некоторые данные с помощью двух команд sed, но я не совсем уверен, как удалить остальные, которые мне не нужны, или сопоставить только то, что мне нужно. Мы будем благодарны за некоторую помощь.

РЕДАКТИРОВАТЬ: Вот что я знаю о команде:

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.://'

Вот результат (просто нужно добавить разделители):

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

Есть ли более простой способ сделать то, что я сделал?

1
nosforever 25 Ноя 2016 в 20:55

5 ответов

Лучший ответ

Вывод команды sensors сильно зависит от файла конфигурации. Например, можно переименовать ярлыки с конфигурацией, аналогичной на следующее:

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

При такой конфигурации вывод команды sensors будет выглядеть следующим образом:

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)

Однако в утилите sensors есть переключатель -u, который выводит простые для анализа необработанные данные. В необработанном режиме названия функций микросхемы печатаются в стандартных форматах, таких как temp1_input, temp1_max, temp1_crit и temp1_crit_alarm, например:

acpitz-virtual-0
Adapter: Virtual device
temp1:
  temp1_input: 64.000
  temp1_crit: 120.000
temp2:
  temp2_input: 30.000
  temp2_crit: 120.000

coretemp-isa-0000
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
  ...

Формат по-прежнему не так прост для анализа, как мог бы (подумайте о JSON или XML). Блоки функций микросхемы разделяются новой строкой. Каждый блок начинается с названия чипа. Поэтому вам нужно помнить, когда блок начинается, и печатать, когда блок заканчивается (пустая строка или конец файла).

Возможна реализация алгоритма в AWK. Это возможно даже в SED. Но я считаю эти инструменты неудобными в данном случае. Я бы предпочел использовать более гибкий инструмент, такой как Perl (возможно, я просто больше привык к Perl, чем к AWK).

< Сильный > Пример

sensor-temp.pl

#!/usr/bin/perl
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))
  }
}

< EM> Использование

sensors -u | perl sensors-temp.pl

Пример вывода

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

Скрипт вычисляет среднюю температуру для записей temp\d+_input. Вы можете легко изменить сценарий в соответствии с нашими потребностями. Например, чтобы распечатать список всех "входных" температур для микросхемы, замените последний блок в цикле следующим:

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

Пример вывода

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

< Сильного > P.S .

Код в примерах печатает символы новой строки для каждой микросхемы для ясности. Замените символы новой строки (\n) на "|" или на то, что вы сочтете подходящим для вашего случая.

0
Ruslan Osmanov 26 Ноя 2016 в 18:32

Я уверен, что есть более элегантные способы сделать это, но, возможно, это может помочь:

sensors | egrep -o "\S+-\S+|\+[0-9]+\...C" | egrep "\S+-\S+" -A 1 | sed 's/--/|/g' | head -n -3 | tr '\n' ' '

Если первый grep соответствует только подобным строкам и значениям температуры, второй grep снова соответствует подобным строкам и по одной строке после каждой из них, sed преобразует - ( генерируется вторым grep) в | , затем head удаляет последние 3 строки (это работает только в вашем конкретном выводе), а tr удаляет новые строки.

0
matteo martelli 25 Ноя 2016 в 21:19

Очень неясно, что вы пытаетесь сделать, но это дает результат, который, как вы говорите, вы хотите, из введенных вами входных данных:

$ cat tst.awk
/^[^[:space:]:]+$/ { name = $0 }
name == "k10temp-pci-00c3" { print ts, rec; exit }
$1 == "temp1:" { rec = (rec=="" ? "" : rec "  |  ") name "  -  " $2 }

$ awk -v ts="$(date +'%F %T')" -f tst.awk file
2016-11-26 09:26:35 amdgpu-pci-0100  -  +67.0°C  |  amdgpu-pci-0600  -  +59.0°C  |  amdgpu-pci-0700  -  +64.0°C  |  it8721-isa-0290  -  +43.0°C

Это все, что вы пытаетесь сделать - вывести первые значения temp1 для каждого блока перед k10?

0
Ed Morton 26 Ноя 2016 в 15:27

Вы сказали: «Последний код довольно жестко запрограммирован, и мне он не нравится, потому что он не очень гибкий». Это правда, но я думаю, что эта проблема присуща процессу создания ваших данных, а не инструменту, который используется для генерации желаемого результата. Я придумал это решение. Если вас интересуют подробности используемых мной команд, просто спросите:

 sensors | sed -n -e '/^k10temp-pci-00c3$/,$ s/.*//; /^[^ \\\t]\+$/ H;' \
       -e '/^temp1:/ {s/^temp1:[ \\\t]\+\([+-][0-9]*.[0-9]\+°C\).*/\1/; H;}' \
       -e '$ {x; s/^\n//; :start /\n/ {s/\n/ - /; s/\n/ | /; b start;}; s/^\(.*\)/<Date Time> \1/; p;}'
0
FloHe 28 Ноя 2016 в 03:13
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.://'

sensors - получить необработанный вывод

'/Adapter/d' - удалить строки, содержащие «Адаптер»

'/in/d' - удалить строки, содержащие "в"

's/[)(]//g' - убрать скобку

'/Vbat/d' - удалить строки, содержащие "Vbat"

's/crit.*//' - Удалить все после слова "крит" в строке

's/low.*//' - Удалить все после "low" в строке

'/temp2/d' - удалить строки, содержащие "temp2"

'/temp3/d' - удалить строки, содержащие "temp3"

'/^k10temp-pci-00c3$/,$d' - Удалить все после "k10temp-pci-`00c3"

Последний довольно жестко запрограммирован, и мне он не нравится, потому что он не очень гибкий.

-1
nosforever 25 Ноя 2016 в 20:32