Як змусити ноутбук заснути, коли він досягне деякого низького порогу акумулятора?


24

Я використовую Ubuntu, але у мене є i3 як мій менеджер вікон замість середовища робочого столу.

Коли мій акумулятор досягне 0%, комп'ютер просто різко вимкнеться, без попередження чи нічого.

Чи є простий скрипт або конфігурація, яку я можу налаштувати так, щоб вона переходила до сну, скажімо, 4% акумулятор?

Відповіді:


12

Ось невеликий сценарій, який перевіряє рівень заряду батареї та викликає власну команду, ось pm-hibernateу випадку, якщо рівень акумулятора нижче певного порогу.

#!/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

Це дуже простий сценарій, але я думаю, ви отримаєте ідею і можете легко адаптувати її до своїх потреб. Шлях до рівня акумулятора може бути різним у вашій системі. Трохи більш портативним було б, можливо, використовувати щось на кшталт acpi | cut -f2 -d,отримання рівня акумулятора. Цей скрипт може бути запланований cron, щоб запускати щохвилини. Відредагуйте свій Crontab crontab -eта додайте сценарій:

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

Іншим рішенням буде встановити середовище робочого столу типу Gnome або Xfce (і змінити менеджер вікон на i3). В обох згаданих середовищах зупинки функціонування демонструються демони управління живленням, які дбають про вимкнення комп'ютера. Але я припускаю, що ви навмисно не використовуєте їх і шукаєте більш мінімалістичне рішення.


Гм, я спробував бігти, sleepd -b 40і нічого не сталося після позначки 40%. Я також спробував, sudo sleepd -b 40 -s pm-suspendі нічого не відбувається ...
o_o_o--

@NoamGagliardi Підтверджено, тут також не працює. Крім того, пакет здається незбереженим. Я намагаюся, якщо зможу знайти кращу альтернативу та оновити свою відповідь, інакше я її видалю.
Марко

(TIL " cut".) Сценарій працює! У мене є acpi | cut -f2 -d, | cut -f1 d%- я прочитаю про cron, щоб змусити його працювати самостійно. Спасибі!
o_o_o--

У мене немає /sys/devices/platform/smapi/каталогу. Де я можу знайти залишок відсотка заряду акумулятора? Я використовую власне ядро ​​3.10
Мартін Вегтер

2
@MartinVegter Це залежить від вашого обладнання, ви можете спробувати /sys/class/power_supply/BAT0/capacity. В іншому випадку використовуйте acpiкоманду.
Марко

6

Замість того, щоб зламати власні сценарії, і якщо ви використовуєте Ubuntu як тег підказує, ви можете просто встановити пакет upower. Він повинен бути доступний для всіх похідних Debian, включаючи Ubuntu. За замовчуванням він оснащений конфігурацією, в /etc/UPower/UPower.confякій активує гібридний сон, як тільки рівень акумулятора досягне критичних значень. Типовий рівень для критичного рівня - 2%.

Для користувачів інших дистрибутивів відповідні записи для /etc/UPower/UPower.conf:

PercentageAction=2
CriticalPowerAction=HybridSleep

Ви також можете використовувати TimeActionразом з, UsePercentageForPolicy=falseщоб дозволити виконання дії, коли залишиться лише вказаний час:

TimeAction=120

Допустимі значення CriticalPowerActionє PowerOff, Hibernateі HybridSleep. Якщо HybridSleep встановлений, але він недоступний, буде застосовано сплячий режим. Якщо сплячий режим встановлений, але він недоступний, буде використовуватися PowerOff.

Перевага HybridSleep полягає в тому, що окрім виписування пам'яті у вашу область заміни, вона потім призупиняє роботу системи. Призупинення все ще буде споживати деяку батарею, але якщо ви повернетесь до вичерпання батареї, ви можете набагато швидше відновитись із підвішеної системи, ніж із сплячої. Якщо акумулятор розрядиться, перш ніж повернутися до розетки, ви можете відновити систему зі сплячого режиму, як тільки знову будете живити.


Примітка. Я думаю, що HybridSleepпотрібно мати місце для заміни.

2
Правильний @cipricus, але споживач витончено вирішить вимкнути машину, якщо вона не може перейти у сплячку.
Джош

2

На сьогодні прийнята відповідь чудова, але трохи застаріла для Ubuntu 16.04:

  • Команди для отримання статусу батареї змінилися.
  • Змінені середовища, необхідні для надсилання-повідомлення на роботу , змінилися .
  • Наведений там сценарій більше не працює з крона користувача, оскільки в сплячому режимі потрібен root.
  • systemctl hibernateє кращим pm-hibernate.

Отже, ось сценарій, який я використовую:

#!/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

Змінні середовища, необхідні для notify-sendроботи, створюються за допомогою цього сценарію :

#!/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

Цей файл потрібно запустити при запуску (це можна зробити за допомогою будь-якого способу на ваш вибір; я використовую вбудовані програми Ubuntu в програми запуску ).

Примітка: sudo systemctl hibernate може не працювати з крона. Дотримуйтесь цього, щоб вирішити це.


0

Існує багато способів її впровадження, оскільки існує багато різних схем управління потужністю, що реалізуються залежно від того, що ви встановили.

Цей простий працює для мене в мінімалістичному Debian Jessie без будь-якого середовища на робочому столі, лише з невеликим і швидким менеджером вікон Icewm. (Він оброблений тому, що в іншому випадку просто занадто повільний, і таким чином він перевершує GNOME на набагато кращому апаратному забезпеченні)

Зокрема, я встановив наступні пакети: acpi acpi-fakekey acpi-підтримка acpi-підтримка-acpi-підтримка acpid pm-утиліти, але НІКОЛИ наступного (очистивши їх): gnome * kde * systemd * uswsusp upower laptop-mode-tools спляча політика-1

Тому я просто вклав це /etc/cron.d/battery_low_check(все в один рядок, розділений на читабельність):

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

Це швидке, малоресурсове використання і не залежить від інших демонів (якщо насправді, воно буде ігноровано, якщо вони активні - див. /usr/share/acpi-support/policy-funcsДеталі).

Що це робить: кожні 5 хвилин ( */5- ви можете переходити на кожну хвилину, просто використовуючи, *якщо вам потрібно частіше перевіряти акумулятор), він запитає стан батареї (" acpi - батарея ") та виконуватиме команду після, xargs -riякщо акумулятор " Розряд "(тобто ви не підключені до змінного струму) і стан акумулятора менше 10%(" int ($ 2) <10 "- сміливо налаштовуйте його на свої потреби)

acpi_fakekey 205за замовчуванням надішле KEY_SUSPENDподія ACPI (як би ви натиснули клавішу на ноутбуці з проханням призупинити), яка потім зробить все, що зазвичай робить для вас (налаштовано в /etc/default/acpi-support) - для мене він перезимує на диск.

Ви можете використовувати іншу команду замість acpi_fakekey 205звичайно: like hibernate(з hibernate пакета), s2diskабо s2mem(з uswsusp пакета), pm-suspend-hybrid(від pm-utils package) тощо.

BTW, номери магічних клавіш на зразок KEY_SUSPEND = 205 вище визначені в /usr/share/acpi-support/key-constants(інше цікаве, мабуть, KEY_SLEEP = 142 )


це здається дуже приємним! але чи можна це використовувати із системним таймером замість крона? (приклад тут ) Я перебуваю на Solus OS, де cron відсутній.

@cipricus Я думаю, що так, але я уникаю systemd, тому не можу навести приклад. Здається, я пам'ятаю, що systemd має власні обробники живлення ACPI, тому, якщо ви застрягли з systemd, ви, ймовірно, хочете уникнути зіткнення з цим
Matija Nalis

дякую, я знайшов альтернативу за участю uname: github.com/jerrinfrncs/batterynotif/blob/master/…

0

Мені подобається це рішення, яке частково надихається іншими відповідями: https://github.com/jerrinfrncs/batterynotif , а саме сценарієм batterynotif(uname).sh.

Дивіться сценарій тут: https://github.com/jerrinfrncs/batterynotif/blob/master/batterynotif%28uname%29.sh

Для власного використання я змінив сценарій для введення гібридного сну замість вимкнення, за допомогою команди systemctl hybrid-sleep. (Ця опція потрібна для заміни місця.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.