Jak sprawić, by laptop uśpił się, gdy osiągnie niski poziom naładowania baterii?


24

Używam Ubuntu, ale i3 jako menedżer okien zamiast środowiska pulpitu.

Kiedy poziom naładowania baterii osiągnie 0%, komputer nagle się wyłączy, bez ostrzeżenia lub czegokolwiek innego.

Czy istnieje prosty skrypt lub konfiguracja, którą mogę skonfigurować tak, aby spała przy, powiedzmy 4% baterii?

Odpowiedzi:


12

Oto mały skrypt, który sprawdza poziom naładowania baterii i wywołuje tutaj niestandardowe polecenie pm-hibernate, na wypadek gdyby poziom naładowania baterii był poniżej określonego progu.

#!/bin/sh

###########################################################################
#
# Usage: system-low-battery
#
# Checks if the battery level is low. If “low_threshold” is exceeded
# a system notification is displayed, if “critical_threshold” is exceeded
# a popup window is displayed as well. If “OK” is pressed, the system
# shuts down after “timeout” seconds. If “Cancel” is pressed the script
# does nothing.
#
# This script is supposed to be called from a cron job.
#
###########################################################################

# This is required because the script is invoked by cron. Dbus information
# is stored in a file by the following script when a user logs in. Connect
# it to your autostart mechanism of choice.
#
# #!/bin/sh
# touch $HOME/.dbus/Xdbus
# chmod 600 $HOME/.dbus/Xdbus
# env | grep DBUS_SESSION_BUS_ADDRESS > $HOME/.dbus/Xdbus
# echo 'export DBUS_SESSION_BUS_ADDRESS' >> $HOME/.dbus/Xdbus
# exit 0
#
if [ -r ~/.dbus/Xdbus ]; then
  . ~/.dbus/Xdbus
fi

low_threshold=10
critical_threshold=4
timeout=59
shutdown_cmd='/usr/sbin/pm-hibernate'

level=$(cat /sys/devices/platform/smapi/BAT0/remaining_percent)
state=$(cat /sys/devices/platform/smapi/BAT0/state)

if [ x"$state" != x'discharging' ]; then
  exit 0
fi

do_shutdown() {
  sleep $timeout && kill $zenity_pid 2>/dev/null

  if [ x"$state" != x'discharging' ]; then
    exit 0
  else
    $shutdown_cmd
  fi
}

if [ "$level" -gt $critical_threshold ] && [ "$level" -lt $low_threshold ]; then
  notify-send "Battery level is low: $level%"
fi

if [ "$level" -lt $critical_threshold ]; then

  notify-send -u critical -t 20000 "Battery level is low: $level%" \
    'The system is going to shut down in 1 minute.'

  DISPLAY=:0 zenity --question --ok-label 'OK' --cancel-label 'Cancel' \
    --text "Battery level is low: $level%.\n\n The system is going to shut down in 1 minute." &
  zenity_pid=$!

  do_shutdown &
  shutdown_pid=$!

  trap 'kill $shutdown_pid' 1

  if ! wait $zenity_pid; then
    kill $shutdown_pid 2>/dev/null
  fi

fi

exit 0

To bardzo prosty skrypt, ale myślę, że masz pomysł i możesz go łatwo dostosować do swoich potrzeb. Ścieżka do poziomu baterii może być inna w systemie. Nieco bardziej przenośnym byłoby prawdopodobnie użycie czegoś takiego jak acpi | cut -f2 -d,uzyskanie poziomu naładowania baterii. Skrypt może zostać zaplanowany przez crona tak, aby był uruchamiany co minutę. Edytuj crontab za pomocą crontab -ei dodaj skrypt:

*/1 * * * * /home/me/usr/bin/low-battery-shutdown

Innym rozwiązaniem byłoby zainstalowanie środowiska pulpitu, takiego jak Gnome lub Xfce (i zmiana menedżera okien na i3). Oba wspomniane środowiska destop wyposażone są w demony zarządzania energią, które dbają o wyłączenie komputera. Ale zakładam, że celowo ich nie używasz i szukasz bardziej minimalistycznego rozwiązania.


Hm, próbowałem biec sleepd -b 40i nic się nie stało po znaku 40%. Też próbowałem sudo sleepd -b 40 -s pm-suspendi nic się nie dzieje ...
o_o_o--

@NoamGagliardi Potwierdzono, że tu też nie działa. Ponadto pakiet wydaje się nieobsługiwany. Próbuję znaleźć lepszą alternatywę i zaktualizować swoją odpowiedź, w przeciwnym razie ją usunę.
Marco

(TIL „ cut”.) Skrypt działa! Mam acpi | cut -f2 -d, | cut -f1 d%- przeczytam o cronie, żeby sam działał. Dzięki!
o_o_o--

Nie mam /sys/devices/platform/smapi/katalogu Gdzie mogę znaleźć pozostały procent energii baterii? Używam niestandardowego jądra 3.10
Martin Vegter

2
@MartinVegter To zależy od twojego sprzętu, możesz spróbować /sys/class/power_supply/BAT0/capacity. W przeciwnym razie użyj acpipolecenia.
Marco

6

Zamiast hakować własne skrypty i jeśli używasz Ubuntu, jak sugeruje tag, możesz po prostu zainstalować pakiet upower. Powinien być dostępny na wszystkich pochodnych Debianie, w tym na Ubuntu. Domyślnie jest wyposażony w konfigurację, w /etc/UPower/UPower.confktórej aktywowany jest tryb uśpienia hybrydowego, gdy poziom naładowania akumulatora osiągnie wartości krytyczne. Domyślny poziom krytyczny to 2%.

W przypadku użytkowników innych dystrybucji odpowiednie wpisy /etc/UPower/UPower.confto:

PercentageAction=2
CriticalPowerAction=HybridSleep

Możesz także użyć TimeActionrazem z, UsePercentageForPolicy=falseaby pozwolić na wykonanie akcji, gdy pozostanie tylko określony czas:

TimeAction=120

Poprawne wartości CriticalPowerActionPowerOff, Hibernatei HybridSleep. Jeśli HybridSleep jest ustawiony, ale niedostępny, zostanie użyty tryb hibernacji. Jeśli Hibernacja jest ustawiona, ale niedostępna, zostanie użyte PowerOff.

Zaletą HybridSleep jest to, że oprócz zapisywania pamięci w obszarze wymiany, zawiesza ona system. Zawieszenie nadal zużywa trochę baterii, ale jeśli wrócisz przed wyczerpaniem się baterii, możesz znacznie szybciej wznowić pracę z zawieszonego systemu niż z hibernowanego. Jeśli bateria wyczerpie się przed powrotem do gniazdka, możesz wznowić działanie systemu ze stanu hibernacji po ponownym włączeniu zasilania.


Uwaga: Myślę, że HybridSleepwymaga przestrzeni wymiany.

2
@pricus, który jest poprawny, ale upower z wdziękiem zdecyduje się wyłączyć maszynę zamiast tego, jeśli nie może hibernować.
josch,

2

Aktualnie akceptowana odpowiedź jest świetna, ale nieco przestarzała dla Ubuntu 16.04:

  • Polecenia uzyskania statusu baterii uległy zmianie.
  • Zmienne środowiskowe wymagane do powiadomienia-wysyłania do pracy uległy zmianie .
  • Podany tam skrypt nie działa już z poziomu crona użytkownika, ponieważ hibernacja wymaga rootowania.
  • systemctl hibernatejest lepszy niż pm-hibernate.

Więc tutaj jest zastosowanie skryptu I:

#!/usr/bin/env bash

# Notifies the user if the battery is low.
# Executes some command (like hibernate) on critical battery.
# This script is supposed to be called from a cron job.
# If you change this script's name/path, don't forget to update it in crontab !!

level=$(cat /sys/class/power_supply/BAT1/capacity)
status=$(cat /sys/class/power_supply/BAT1/status)

# Exit if not discharging
if [ "${status}" != "Discharging" ]; then
  exit 0
fi


# Source the environment variables required for notify-send to work.
. /home/anmol/.env_vars

low_notif_percentage=20
critical_notif_percentage=15
critical_action_percentage=10


if [ "${level}" -le ${critical_action_percentage} ]; then
  # sudo is required when running from cron
  sudo systemctl hibernate
  exit 0
fi

if [ "${level}" -le ${critical_notif_percentage} ]; then
  notify-send -i '/usr/share/icons/gnome/256x256/status/battery-caution.png' "Battery critical: ${level}%"
  exit 0
fi

if [ "${level}" -le ${low_notif_percentage} ]; then
  notify-send -i '/usr/share/icons/gnome/256x256/status/battery-low.png' "Battery low: $level%"
  exit 0
fi

Zmienne środowiskowe wymagane notify-senddo pracy są tworzone za pomocą tego skryptu :

#!/usr/bin/env bash

# Create a new file containing the values of the environment variables
# required for cron scripts to work.
# This script is supposed to be scheduled to run at startup.

env_vars_path="$HOME/.env_vars"

rm -f "${env_vars_path}"
touch "${env_vars_path}"
chmod 600 "${env_vars_path}"

# Array of the environment variables.
env_vars=("DBUS_SESSION_BUS_ADDRESS" "XAUTHORITY" "DISPLAY")

for env_var in "${env_vars[@]}"
do
    echo "$env_var"
    env | grep "${env_var}" >> "${env_vars_path}";
    echo "export ${env_var}" >> "${env_vars_path}";
done

Ten plik musi być uruchamiany podczas uruchamiania (można to zrobić dowolną wybraną metodą; używam wbudowanych aplikacji startowych Ubuntu ).

Uwaga: sudo systemctl hibernate może nie działać z crona. Postępuj zgodnie z tym, aby go rozwiązać.


0

Istnieje wiele sposobów jego wdrożenia, ponieważ istnieje wiele różnych schematów zarządzania energią, w zależności od tego, co zainstalowałeś.

Ten prosty działa dla mnie na minimalistycznym Debianie Jessie bez żadnego środowiska graficznego, tylko z małym i szybkim menedżerem okien icewm. (Jest zmniejszany, ponieważ w przeciwnym razie jest po prostu zbyt wolny, i w ten sposób przewyższa GNOME na znacznie lepszym sprzęcie)

W szczególności mam zainstalowanych następujące pakiety: acpi acpi-fakekey acpi-support acpi-support-base acpid pm-utils, ale NIE JESTEM z następujących (po ich wyczyszczeniu): gnome * kde * systemd * uswsusp upower laptop-mode-tools hibernacja policykit-1

Więc po prostu wstawiłem to /etc/cron.d/battery_low_check(wszystko w jednym wierszu, podzielone dla czytelności):

*/5 * * * *   root  acpi --battery | 
   awk -F, '/Discharging/ { if (int($2) < 10) print }' | 
   xargs -ri acpi_fakekey 205

Jest szybki, zużywa niewiele zasobów i nie zależy od innych diamonów (jeśli w rzeczywistości zostaną zignorowane, jeśli będą aktywne - zobacz /usr/share/acpi-support/policy-funcsszczegóły).

Co robi: co 5 minut ( */5- możesz przejść do każdej minuty, używając tylko tego, *jeśli potrzebujesz częściej sprawdzać baterię), sonduje stan baterii („ acpi - akumulator ”) i wykonuje polecenie xargs -ridopiero wtedy, gdy bateria jest „ Rozładowanie ”(to znaczy, że nie masz połączenia z prądem przemiennym), a stan baterii jest mniejszy niż 10%(„ int (2 $) <10 ”- możesz go dostosować do swoich potrzeb)

acpi_fakekey 205domyślnie wyśle KEY_SUSPENDzdarzenie ACPI (tak jak nacisnąłeś klawisz na laptopie z prośbą o zawieszenie), co zrobi to, co zwykle dla ciebie robi (skonfigurowane w /etc/default/acpi-support) - dla mnie hibernuje na dysk.

Możesz acpi_fakekey 205oczywiście użyć innej komendy zamiast : like hibernate(z pakietu hibernacji) s2disklub s2mem(z pakietu uswsusp), pm-suspend-hybrid(z pakietu pm-utils) itp.

BTW, numery magicznych klawiszy, takie jak KEY_SUSPEND = 205 powyżej są zdefiniowane w /usr/share/acpi-support/key-constants(inny interesujący to prawdopodobnie KEY_SLEEP = 142 )


to wydaje się bardzo miłe! ale czy można tego użyć z systemowym zegarem zamiast crona? (przykład tutaj ) Jestem na Solus OS, gdzie cron jest nieobecny.

@cipricus Chyba tak, ale unikam systemd, więc nie mogę dać przykładu. Wydaje mi się, że pamiętam, że systemd ma własne moduły obsługi zasilania ACPI, więc jeśli utkniesz w systemie, prawdopodobnie nie chciałbyś się z tym kolidować
Matija Nalis

dzięki, znalazłem alternatywę obejmującą uname: github.com/jerrinfrncs/batterynotif/blob/master/…

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.