понедельник, 1 января 2007 г.

PowerCheck v 0.1

Upd: 31/08/2010 Поправил для обеспечения совместимости с 10.04

Скрипт, показывающий основные параметры системы, влияющие на энергопотребление





#! /bin/bash

#-------------------------------------------------
# Скрипт отображения состояния системных параметров,
# влияющих на энергопотребление
# v0.01 - начальная версия, отображающая состояние
# v0.1  - текущая версия. Добавлен выбор пользователя
#         и показана команда для изменения состояния 
#         выбранного параметра
# v0.11 - Небольшие изменения для совместимости с 10.04
#
#
# В планах:
# * Вычислять среднее потребление энергии за прошедший период
# * Изменять состояние по выбору пользователя
# * Вычислять эффект по сохранению энергии от изменения


#-------------------------------------------------
# Функция вывода на экран строки 
# $1 - h(eader), d(escripion), v(alue), c(ommand), o(out command)
#      В зависимости от параметра назначаются цвет фона и шрифта
# $2 - Y
# $3 - X
# $4 - string 
# $5 - len string  - Длина строки для стирания мусора под выводом
PutStr()
{
  DUMMY_STR="                                                                                "
  case "$1" in
    c)
      FN_COLOR=4 ;;
    h)
      BG_COLOR=1 ; FN_COLOR=7 ;;
    d)
      BG_COLOR=7 ; FN_COLOR=1 ;;
    o)
      BG_COLOR=3 ; FN_COLOR=0 ;;
    v)
      BG_COLOR=7 ; FN_COLOR=0 ;;
  esac

  tput setb $BG_COLOR ; tput setf $FN_COLOR
  if [ "$5" ]
   then
     EMPTY_SRT=${DUMMY_STR:1:$5}
     tput cup $2 $3
     echo -n "$EMPTY_SRT"
  fi
  tput cup $2 $3
  echo -n "$4"
  tput setb 7 ; tput setf 0
}

#-------------------------------------------------
# Выводит на экран строку с командой управления питанием 
# для конкретного устройства
# В следующей версии будет ее исполнять
Command()
{
  PutStr "o" 21 2 "$1" 76
}

#-------------------------------------------------
# Выводит на экран описаниие команды
Description()
{
  if [ "$2" ]
  then
    PutStr "d" 19 2 "$1" 50
    PutStr "d" 20 2 "$2" 50
  else
    PutStr "d" 19 2 " " 50
    PutStr "d" 20 2 "$1" 50
  fi
}

#-------------------------------------------------
# Выводит на экран промпт
Prompt()
{
  PutStr "v" 18 2 "Command (A,B,C,D,E,F,G,I,K,L,M,P,R,S,T,U,W or Q):"
}

#-------------------------------------------------
# Выаодит на экран статические заголовки и сообщения
Put_Head()
{
  PutStr "h" 0 0 "_________CPU1__CPU2__"
  PutStr "d" 1 0 "Governor"
  PutStr "c" 1 0 "G"
  PutStr "d" 2 0 "Throttl"
  PutStr "c" 2 0 "T"
  PutStr "d" 3 0 "Tune Multi-Core:"
  PutStr "c" 3 11 "C"

  PutStr "h" 5 0 "SCSI0_____SCSI1_____SCSI2_____SCSI3__"

  PutStr "h" 0 26 "USB1___USB2___USB3___USB4___USB5___USB6___USB7___USB8"

  PutStr "d" 2 26 "Autosuspend:"
  PutStr "c" 2 26 "A"
  PutStr "h" 8 0 "Tuning VM_______________"
  PutStr "d" 9 0 "Swappiness:"
  PutStr "c" 9 0 "S"
  PutStr "d" 10 0 "Dirty Writeback:"
  PutStr "c" 10 6 "W"
  PutStr "d" 11 0 "Dirty Expire:"
  PutStr "c" 11 6 "E"
  PutStr "d" 12 0 "Dirty Background:"
  PutStr "c" 12 6 "B"
  PutStr "d" 13 0 "Dirty Ratio:"
  PutStr "c" 13 6 "R"
  PutStr "h" 8 30 "Misk_______________"
  PutStr "d" 9 30 "Fan speed:"
  PutStr "c" 9 30 "F"
  PutStr "d" 10 30 "CPU Temp:"
  PutStr "d" 11 30 "Brightness:"
  PutStr "d" 12 30 "WiFi Power:"
  PutStr "c" 12 35 "P"
  PutStr "d" 13 30 "Intel HDA:"
  PutStr "c" 13 30 "I"
  PutStr "d" 14 30 "Laptop mode:"
  PutStr "c" 14 30 "L"

  PutStr "h" 3 53 "HDD" 26
  PutStr "d" 4 53 "hdparm -M:"
  PutStr "c" 4 61 "M"
  PutStr "d" 5 53 "STate:"
  PutStr "c" 5 54 "T"

  PutStr "h" 8 53 "Ethernet" 26
  PutStr "d" 9 53 "SpeeD:"
  PutStr "c" 9 57 "D"
  PutStr "d" 10 53 "WaKe-on:"
  PutStr "c" 10 55 "K"

  PutStr "h" 12 53 "Battery" 26
  PutStr "d" 13 53 "Capacity:"
  PutStr "d" 14 53 "Remain:"
  PutStr "d" 15 53 "State:"
  PutStr "d" 16 53 "Rate:"

  PutStr "d" 23 2 "Start time:"
  PutStr "v" 23 14 `eval date +%H:%M:%S`
  PutStr "d" 23 24 "Current time:"
  PutStr "d" 23 49 "(c) http://axa-ru.blogspot.com"
}

#-------------------------------------------------
# Считывет состояние переменных и выводит их на экран
Put_Value()
{
  tput sc                         #запоминаем положение курсора  
  read CPU0GOV < "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
  if [ $CPU0GOV = "powersave" ]
    then
      CPU0GOV="psave"
  fi
  CPU0GOV=${CPU0GOV:0:5}
  read CPU1GOV < "/sys/devices/system/cpu/cpu1/cpufreq/scaling_governor"
  if [ $CPU1GOV = "powersave" ]
    then
      CPU1GOV="psave"
  fi
  CPU1GOV=${CPU1GOV:0:5}
  CPU0TX=`eval cat "/proc/acpi/processor/CPU0/throttling" | grep "active state"`
  CPU0TX=${CPU0TX:25:2}
  CPU1TX=`eval cat "/proc/acpi/processor/CPU1/throttling" | grep "active state"`
  CPU1TX=${CPU1TX:25:2}
  PutStr "v" 1 9 "$CPU0GOV"
  PutStr "v" 1 15 "$CPU1GOV"
  PutStr "v" 2 9 "$CPU0TX"
  PutStr "v" 2 15 "$CPU1TX"
  read MULTI_CORE < "/sys/devices/system/cpu/sched_mc_power_savings"
  PutStr "v" 3 18 "$MULTI_CORE"

  read SCSI0 < "/sys/class/scsi_host/host0/link_power_management_policy"
  read SCSI1 < "/sys/class/scsi_host/host1/link_power_management_policy"
  read SCSI2 < "/sys/class/scsi_host/host2/link_power_management_policy"
  read SCSI3 < "/sys/class/scsi_host/host3/link_power_management_policy"
  SCSI0=${SCSI0:0:7}
  SCSI1=${SCSI1:0:7}
  SCSI2=${SCSI2:0:7}
  SCSI3=${SCSI3:0:7}
  PutStr "v" 6 0 "$SCSI0"
  PutStr "v" 6 10 "$SCSI1"
  PutStr "v" 6 20 "$SCSI2"
  PutStr "v" 6 30 "$SCSI3"
  
  read USB1 < "/sys/bus/usb/devices/usb1/power/level"
  read USB2 < "/sys/bus/usb/devices/usb2/power/level"
  read USB3 < "/sys/bus/usb/devices/usb3/power/level"
  read USB4 < "/sys/bus/usb/devices/usb4/power/level"
  read USB5 < "/sys/bus/usb/devices/usb5/power/level"
  read USB6 < "/sys/bus/usb/devices/usb6/power/level"
  read USB7 < "/sys/bus/usb/devices/usb7/power/level"
  read USB8 < "/sys/bus/usb/devices/usb8/power/level"
  PutStr "v" 1 26 "$USB1"
  PutStr "v" 1 33 "$USB2"
  PutStr "v" 1 40 "$USB3"
  PutStr "v" 1 47 "$USB4"
  PutStr "v" 1 54 "$USB5"
  PutStr "v" 1 61 "$USB6"
  PutStr "v" 1 68 "$USB7"
  PutStr "v" 1 75 "$USB8"
  read USB_AS < "/sys/module/usbcore/parameters/autosuspend"
  PutStr "v" 2 40 "$USB_AS"

  read SWAPINESS < "/proc/sys/vm/swappiness"
  read DIRTY_WRB < "/proc/sys/vm/dirty_writeback_centisecs"
  read DIRTY_EXP < "/proc/sys/vm/dirty_expire_centisecs"
  read DIRTY_BKG < "/proc/sys/vm/dirty_background_ratio"
  read DIRTY_RAT < "/proc/sys/vm/dirty_ratio"
  PutStr "v" 9 18 "$SWAPINESS" 6
  PutStr "v" 10 18 "$DIRTY_WRB" 6
  PutStr "v" 11 18 "$DIRTY_EXP" 6
  PutStr "v" 12 18 "$DIRTY_BKG" 6
  PutStr "v" 13 18 "$DIRTY_RAT" 6
  
  FAN=`eval grep "speed:" "/proc/acpi/ibm/fan"`
  FAN=${FAN:8:4}
  PutStr "v" 9 44 "$FAN" 4
  read CPU_THERM < "/proc/acpi/ibm/thermal"
  CPU_THERM=${CPU_THERM:14:2}
  PutStr "v" 10 44 "$CPU_THERM"
  BRIGTH=`eval grep "current" "/proc/acpi/video/VID/LCD0/brightness"`
  BRIGTH=${BRIGTH:9:3}
  PutStr "v" 11 44 "$BRIGTH" 3
#  для Ubuntu < 10.04
#  read WIFI < "/sys/bus/pci/drivers/iwlagn/0000:03:00.0/power_level"
#  WIFI=${WIFI:29:1}
#  для Ubuntu >= 10.04
  read WIFI < "/sys/bus/pci/drivers/iwlagn/0000:03:00.0/tx_power"
  PutStr "v" 12 44 "$WIFI" 3
  read INTEL_HDA < "/sys/module/snd_hda_intel/parameters/power_save"
  PutStr "v" 13 44 "$INTEL_HDA"
  read LAPTOP_MODE < "/proc/sys/vm/laptop_mode"
  PutStr "v" 14 44 "$LAPTOP_MODE"

  HDD_ACCUST=`eval hdparm -M /dev/sda | grep "acoustic"`
  HDD_ACCUST=${HDD_ACCUST:17:3}
  PutStr "v" 4 65 "$HDD_ACCUST"
  HDD_STATE=`eval hdparm -C /dev/sda | grep "state is:"`
  HDD_STATE=${HDD_STATE:18:12}
  PutStr "v" 5 65 "$HDD_STATE" 12
  
  ETH_SPEED=`eval ethtool eth0 | grep "Speed:"`
  ETH_SPEED=${ETH_SPEED:8:16}
  PutStr "v" 9 63 "$ETH_SPEED" 16
  
#  ethtool eth0 | grep "Wake-on:" > /tmp/tst.tmp 
#  read ETH_WOL < /tmp/tst.tmp
#  read ETH_WOL < "/tmp/tst.tmp"
#  ETH_WOL=${ETH_WOL:4:10}
#  PutStr "v" 10 63 "$ETH_WOL" 16
  
  BAT_FCAP=`eval cat "/proc/acpi/battery/BAT0/info" | grep "last full capacity:"`
  BAT_FCAP=${BAT_FCAP:25:9}
  PutStr "v" 13 63 "$BAT_FCAP"
  BAT_RCAP=`eval cat "/proc/acpi/battery/BAT0/state" | grep "remaining capacity:"`
  BAT_RCAP=${BAT_RCAP:25:9}
  PutStr "v" 14 63 "$BAT_RCAP" 9
  BAT_CHRG=`eval cat "/proc/acpi/battery/BAT0/state" | grep "charging"`
  BAT_CHRG=${BAT_CHRG:25:12}
  PutStr "v" 15 63 "$BAT_CHRG" 12
  BAT_RATE=`eval cat "/proc/acpi/battery/BAT0/state" | grep "present rate:"`
  BAT_RATE=${BAT_RATE:25:9}
  PutStr "v" 16 63 "$BAT_RATE" 9

  PutStr "v" 23 38 `eval date +%H:%M:%S` 8  
  tput rc                         #восстанавливаем положение курсора  
}

#-------------------------------------------------
# Обработчики команд пользователя

#A, Autosuspend
CmdAutosusp()
{
  Command "echo 1 >/sys/module/usbcore/parameters/autosuspend"
  Description "Enable autosuspend for usb devices"
}
#B, Dirty Background
CmdDirtyBkg()
{
  Command "echo 60 > /proc/sys/vm/dirty_background_ratio"
  Description "Минимальный процент памяти, где позволено" "хранить старые данные вместо записи на диск"
}
#C, Tune Multi-Core
CmdMulticore()
{
  Command "echo 1 > /sys/devices/system/cpu/sched_mc_power_savings"
  Description "Управление многопоточностью процессора"
}
#D, Ethernet SpeeD
CmdEthspeed()
{
  Command "ethtool -s eth0 autoneg off speed 100"
  Description "Отключение гигабитного интерфейса"
}
#G, CPU Governor
CmdCPUGov()
{
  Command "echo powersave > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
  Description "Управление частотой процессоров"
}
#E, Dirty Expire
CmdDirtyExp()
{
  Command "echo 0 > /proc/sys/vm/dirty_expire_centisecs"
  Description "Насколько старыми должны быть данные," "что бы ядро записало их на диск"
}
#F, Fan speed
CmdFan()
{
  Command ""
  Description "Скорость вентилятора охлаждения"
}
#I, Intel HDA powersave
CmdHDA()
{
  Command "echo 10 > /sys/module/snd_hda_intel/parameters/power_save"
  Description "Управление потреблением звуковой подсистемы"
}
#K, Ethernet WaKe-on
CmdEthwake()
{
  Command "ethtool -s eth0 wol d"
  Description "Disable WOL"
}
#L, Laptop mode
CmdLaptop()
{
  Command "echo 5 > /proc/sys/vm/laptop_mode"
  Description "Enable Laptop mode"
}
#M, HDD silent mode
CmdHddSilent()
{
  Command "hdparm -M 128 /dev/sda"
  Description "set acoustic management (128: quiet, 254: fast)"
}
#P, WiFi Power
CmdWifipower()
{
  Command "echo 5 > /sys/bus/pci/drivers/iwlagn/0000:03:00.0/power_level"
  Description "Управление мощностью WiFi"
}
#R, Dirty Ratio
CmdDirtyratio()
{
  Command "echo 95 > /proc/sys/vm/dirty_ratio"
  Description "Максимальный размер памяти в процентах, для хранения" "грязных данных до записи их на диск."
}
#S, Swapiness
CmdSwapiness()
{
  Command "echo 10 > /proc/sys/vm/swappiness"
  Description "процентах свободной памяти, при котором" "система сбрасывает память в swap"
}
#T, HDD Standby
CmdHddStandby()
{
  Command "hdparm -y /dev/sda"
  Description "put HDD in standby mode"
}
#U, Ethernet DUplex
CmdEthdupl()
{
  Command " "
  Description " "
}
#W, Dirty Writeback
CmdDirtywrback()
{
  Command "echo 1500 > /proc/sys/vm/dirty_writeback_centisecs"
  Description "Как часто ядро должно проверять есть ли измененные" "данные для записи на диск"
}

#-------------------------------------------------
# Чтение команд пользователя
Process()
{
  read -n 1 _ANS

  case ${_ANS} in
    [A]) CmdAutosusp;;
    [B]) CmdDirtyBkg;;
    [C]) CmdMulticore;;
    [D]) CmdEthspeed;;
    [E]) CmdDirtyExp;;
    [F]) CmdFan;;
    [G]) CmdCPUGov;;
    [I]) CmdHDA;;
    [K]) CmdEthwake;;
    [L]) CmdLaptop;;
    [M]) CmdHddSilent;;
    [P]) CmdWifipower;;
    [R]) CmdDirtyratio;;
    [S]) CmdSwapiness;;
    [T]) CmdHddStandby;;
    [U]) CmdEthdupl;;
    [W]) CmdDirtywrback;;
    [Q])  exit;;
  esac
  unset _ANS
}

#-------------------------------------------------
#
UpdateValue()
{
  tput civis
  Put_Value
  tput cnorm
}


#-------------------------------------------------
# Обработчик прерываний по таймеру
TIMER_INTERRUPT=14
TIMELIMIT=5             # Сигнал от таймера через 5 сек.

# Ожидает $TIMELIMIT секунд, затем посылает sigalarm в скрипт.
TimerOn()
{
#  sleep $TIMELIMIT && kill -s 14 $ &
  # В Ubuntu 10.04 работает такая конструкция
  sleep $TIMELIMIT && kill -s 14 $$ &
}

# Здесь обрабатываются прерывания по таймеру
Int14Vector()
{
  UpdateValue
  TimerOn
}  

# Установка прерываний по таймеру
# Timer interrupt (14) subverted for our purposes.
trap Int14Vector $TIMER_INTERRUPT

TimerOn          # Запускаем таймер

#-------------------------------------------------
#  Главный цикл
# Usage: "sudo pchk.sh -b"
#                       ^
# Можно поставить любой-+
#     параметр
tput clear
Put_Head

if [ -z $1 ]
then
  Put_Value
else
  while [ 1 ]
  do
    Prompt
    Process
  done
fi 

exit 0