neděle 31. ledna 2010

Automatické vypnutí/uspání počítače po nastavené době

Poslední aktualizace 26.5.2010 - vylepšena funkčnost, ošetřeny výjimky skriptu Shutdown-timer.

K pohodlnější, mocnější a uživatelsky přítulnější aplikaci pro vypínání, uspávání i vraždění napsané v Pythonu, se dostanete kliknutím na odkaz Shutdown GTimer v záhlaví této stránky.

Každý může někdy potřebovat vypnout, nebo uspat počítač až po určité době, kdy to nebude moct udělat sám. Třeba si pustíte večer film a máte v plánu u něj usnout. Když jsem před lety přešel z Windows XP na Ubuntu, začal jsem, jak  jsem byl zvyklý, hledat program, který by mi tuto možnost dal. Nic jsem nemohl najít, až jsem nakonec objevil jednu KDE aplikaci, která pod Gnome fungovala jen občas, jak měla náladu. Nakonec jsem přišel na to, proč takových aplikací moc není - vždyť tu přeci máme ten mocný příkazový řádek! ...



 Stačilo zadat do Terminálu:

$ sudo shutdown -hP +120

a počítač se vypnul za dvě hodiny. Z toho jsem byl nadšený, tak jednoduché řešení! Radost mi kazil jen fakt, že pár minut před koncem odpočtu počítač každou minutu hlasitě pípnul přes interní PC speaker, což mi zrovna v usínání nepomáhalo. Tak jsem našel metodu jak se toho kraválu zbavit. Zkrátka jsem nejdřív ze systému dočasně odstranil modul, který ovládá repráček na základní desce:

$ sudo rmmod pcspkr

Dá se to samozřejmě řešit i jinak, že mě to nenapadlo rovnou..:

$ sudo bash -c "sleep 7200; shutdown -hP now"

Pokud použijete první dvě zmíněné možnosti, není možné odpočet přerušit pouhým zavřením okna terminálu - Tenkrát mi to nějak nešlo, ale dneska mi to jde :) Stačí i klasicky Ctrl+c. Další možností je použít příkaz shutdown s přepínačem -c, pokud jste spustili shutdown na pozadí.

$ sudo shutdown -c

Pak tu máme systém acpi a jeho skripty v adresáři /etc/acpi/ , které umí zprostředkovat i třeba simulaci stisku multimediálních tlačítek, včetně tlačítek "Power" a "Sleep". Jsou zde i skripty pro uspávání do RAM a hibernaci, které můžete volat takto:

$ sudo /etc/acpi/sleep.sh
$ sudo /etc/acpi/hibernate.sh

Ale stále je tu ta potřeba zadávat heslo. To lze obejít buď přidáním výjimky so souboru /etc/sudoers/, nebo třeba využitím služeb pro správu napájení na systému D-Bus, což nevyžaduje žádné zásahy do systému.   K dispozici je tu  SystemPowerManagement přítele HALa (Ubuntu 8.04-9.04), nebo ConsoleKit a DeviceKit (U9.10), či ConsoleKit a UPower (U10.04 a novější).
Níže je vždy první příkaz pro HAL (U 8.04 - 9.04) a druhý pro ConsoleKit/Upower (U 10.04 a novější):

Vypnutí systému:
$ dbus-send --system --print-reply --dest=org.freedesktop.Hal /org/freedesktop/Hal/devices/computer org.freedesktop.Hal.Device.SystemPowerManagement.Shutdown
$ dbus-send --system --print-reply --dest=org.freedesktop.ConsoleKit /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Stop

A pokud chceme počítač jen uspat:
$ dbus-send --system --print-reply --dest=org.freedesktop.Hal /org/freedesktop/Hal/devices/computer org.freedesktop.Hal.Device.SystemPowerManagement.Suspend int32:0
$ dbus-send --system --print-reply --dest=org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower.Suspend
Tato metoda nabízí rovnou svůj vlastní časovač, stačí dopsat počet vteřin za dvojtečku na konci.

Nebo můžeme hibernovat:
$ dbus-send --system --print-reply --dest=org.freedesktop.Hal /org/freedesktop/Hal/devices/computer org.freedesktop.Hal.Device.SystemPowerManagement.Hibernate
$ dbus-send --system --print-reply --dest=org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower.Hibernate

No a nakonec to strčíme do jednoduchého skriptu, který nám zpožděné vypínání systému co nejvíce zpříjemní:

shutdown-timer.sh    (kliknutím stáhnete)
#!/bin/bash

if PID=`pidof -x "$0"`; then
  if echo "$PID" | grep -q '\ '; then
# máme více procesů, kill'em all!
notify-send --icon gnome-shutdown "Shutdown timer" "Odpočet zrušen!" &
    killall `basename $0`
  fi
else
  echo "Nejsem schopen najít ani sám sebe, raději končím.."; exit 1
fi

if [ `dbus-send --system --print-reply --dest=org.freedesktop.Hal /org/freedesktop/Hal/devices/computer org.freedesktop.DBus.Introspectable.Introspect | grep -E "\"Hibernate\"|\"Shutdown\"|\"Suspend\"" | wc -l` == 3 ]
  then
     cmdp="dbus-send --system --print-reply --dest=org.freedesktop.Hal /org/freedesktop/Hal/devices/computer org.freedesktop.Hal.Device.SystemPowerManagement."; serv1=1

elif [ `dbus-send --system --print-reply --dest=org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.DBus.Introspectable.Introspect | grep -E "\"Hibernate\"|\"Suspend\"" | wc -l` == 2 ];then
  cmdp="dbus-send --system --print-reply --dest=org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower."; serv2=1

fi

[ `dbus-send --system --print-reply --dest=org.freedesktop.ConsoleKit /org/freedesktop/ConsoleKit/Manager org.freedesktop.DBus.Introspectable.Introspect | grep "\"Stop\"" | wc -l` == 1 ] && serv3=1



no_service()
{
zenity --error --text "V systému není přítomna potřebná\n služba, ukončuji aplikaci"; exit 1
}

case $1 in
  --suspend)
    [[ ! "$serv1" && ! "$serv2" ]] && no_service
    mod="uspání"
    cmd="${cmdp}Suspend int32:0";;
  --hibernate)
    [[ ! "$serv1" && ! "$serv2" ]] && no_service
    mod="hibernace"
    cmd="${cmdp}Hibernate";;
  *)
    [[ ! "$serv1" && ! "$serv3" ]] && no_service
    mod="vypnutí"
    if [ $serv1 ]; then
      cmd="${cmdp}Shutdown"
    else
       cmd="dbus-send --system --print-reply --dest=org.freedesktop.ConsoleKit /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Stop"
    fi;;
esac

while :; do
  time=`zenity --entry --title 'Shutdown timer' --text 'Zadej čas do '"$mod"' PC v minutách' --entry-text=120` || exit 1
  echo "$time" | grep -Eq '^[0-9]{1,4}$' && break
notify-send --icon dialog-warning "Shutdown timer" "Špatné zadání!
povelená jsou pouze celá čísla
v rozsahu 0 - 9999" &

done
notify-send --icon gnome-shutdown "Shutdown timer" "$time minut do $mod počítače" &

for ((i=1;i<=$time;i++)); do
  [[ $i == $(($time)) ]] && notify-send --icon dialog-warning "Shutdown timer" "1 minuta do $mod počítače!" &
  sleep 60
done

eval "$cmd"

Nezapomeňte nastavit spustitelný příznak a pokud ještě nemáte, je třeba si nainstalovat balík libnotify-bin. Skript je možno spouštět z jakéhokoli umístění.
Po spuštění budete vyzváni k zadání času v minutách, je přednastavena výchozí hodnota 120 minut (změňte podle vlastní potřeby na řádku t=`zenity --entry --title 'Shutdown timer' --text 'Zadej čas do '$mod' PC v minutách' --entry-text=120`) a po jeho potvrzení se zobrazí informační bublina se zadanou hodnotou a spustí odpočet. Zadáte-li jiné znaky, než číslice, nebo nezadáte nic, upozorní vás bublina na špatné zadání a budete vyzváni k zadání znovu. Minutu před koncem odpočtu budete na blížící se vypnutí počítače ještě upozorněni, to je taková pojistka, abyste pak náhodou nebyli překvapeni. A nakonec, opětovným spuštěním skriptu před uplynutím nastavené doby, bude odpočet zrušen. Pokud budete chtít počítač jen uspat do RAM, či hibernovat na disk, můžete využít přepínače --suspend a --hibernate (/cesta/ke/skriptu/shutdown-timer.sh --suspend).

Když si vytvoříte spouštěč na Panel, Plochu, nebo do vašeho oblíbeného doku (Cairo-Dock, AWN, ..), můžete skript spouštět kliknutím myši, nebo si můžete nastavit klávaesovou zkratku. A zrovna tak odpočet kdykoli přerušíte. Viz obrázek na začátku článku, kliknutím na něj se zobrazí další obrázky z použití aplikace.

Funkčnost skriptu otestována na Ubuntu 8.04, 9.04, 9.10, 10.4, Debian Squeeze.

Související článek: Vlastní skript spouštěný při suspend / resume

2 komentáře:

  1. Používám pro automatické vypnutí po určité době Kshutdown

    OdpovědětVymazat
  2. jses borec ;D

    OdpovědětVymazat

Zkuste prosím při komentováni používat místo volby Anonymní volbu Název/adresa URL, kde vyplníte nějakou přezdívku, adresu zadávat nemusíte. Je docela divné, když je tu X Anonymních a nedají se rozlišit. Díky.

Pokud by se vám náhodou odeslaný komentář na stránce nezobrazil, vytáhnu ho z koše hned jak si toho všimnu. I Google spam filter se občas sekne.