Como faço meu laptop dormir quando atinge algum limite de bateria fraca?

23

Estou usando o Ubuntu, mas tenho o i3 como gerenciador de janelas em vez de um ambiente de área de trabalho.

Quando minha bateria atingir 0%, o computador será desligado abruptamente, sem aviso ou qualquer coisa.

Existe um roteiro ou configuração simples que eu possa configurar para que ele durma em, digamos, 4% de bateria?

    
por o_o_o-- 25.07.2013 / 18:35

5 respostas

12

Aqui está um pequeno script que verifica o nível da bateria e chama um comando personalizado, aqui pm-hibernate , caso o nível da bateria esteja abaixo de um certo limite.

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

É um roteiro muito simples, mas acho que você entende e pode adaptá-lo facilmente às suas necessidades. O caminho para o nível da bateria pode ser diferente no seu sistema. Um pouco mais portátil provavelmente seria usar algo como acpi | cut -f2 -d, para obter o nível da bateria. Este script pode ser agendado pelo cron para ser executado a cada minuto. Edite seu crontab com crontab -e e adicione o script:

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

Outra solução seria instalar um ambiente de desktop como o Gnome ou o Xfce (e mudar o gerenciador de janelas para o i3). Ambos os ambientes de destinação mencionados apresentam daemons de gerenciamento de energia que cuidam de desligar o computador. Mas eu assumo que você deliberadamente não os usa e está procurando por uma solução mais minimalista.

    
por 25.07.2013 / 18:54
4

Em vez de hackear seus próprios scripts e se você estiver usando o Ubuntu como a tag sugere, você pode simplesmente instalar o pacote superior. Ele deve estar disponível em todos os derivados do Debian, incluindo o Ubuntu. Por padrão, ele vem com uma configuração em /etc/UPower/UPower.conf , que ativa o sono híbrido quando o nível da bateria atinge valores críticos. O padrão para o nível crítico é de 2%.

Para usuários de outras distribuições, as entradas relevantes para /etc/UPower/UPower.conf são:

PercentageAction=2
CriticalPowerAction=HybridSleep

Você também pode usar TimeAction junto com UsePercentageForPolicy=false para permitir que a ação seja executada quando o tempo especificado for deixado:

TimeAction=120

Os valores válidos para CriticalPowerAction são PowerOff , Hibernate e HybridSleep . Se HybridSleep estiver definido, mas não disponível, o Hibernate será usado. Se o Hibernate estiver definido, mas não disponível, o PowerOff será usado.

A vantagem do HybridSleep é que, além de gravar a memória na sua área de troca, ela suspende o sistema. Suspender ainda vai consumir alguma bateria, mas se você voltar antes que a bateria acabe, você pode retomar muito mais rapidamente a partir de um sistema suspenso do que de um sistema hibernado. Caso a bateria acabe antes de você voltar a um soquete de energia, você pode reiniciar o sistema da hibernação quando tiver energia novamente.

    
por 21.10.2016 / 13:32
3

A resposta atualmente aceita é ótima, mas um pouco desatualizada para o Ubuntu 16.04:

  • Os comandos para obter o status da bateria foram alterados.
  • As variáveis de ambiente necessárias para o envio de notificações para o trabalho mudaram .
  • O script fornecido não funciona mais no cron do usuário, pois o modo de hibernação requer raiz.
  • systemctl hibernate é o preferido em relação a pm-hibernate .

Então, aqui é o script que eu uso:

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

As variáveis de ambiente necessárias para o notify-send funcionar são criadas usando este script :

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

Este arquivo precisa ser executado na inicialização (pode ser feito usando qualquer método de sua escolha; eu uso o builtin do Ubuntu Aplicativos de inicialização ).

Observação: sudo systemctl hibernate pode não funcionar no cron. Siga isso para resolvê-lo.

    
por 11.06.2016 / 12:17
1

Existem muitas maneiras de implementá-lo, pois existem muitos esquemas de gerenciamento de energia diferentes implementados dependendo do que você instalou.

Esse simples trabalho para mim no minimalista Debian Jessie, sem nenhum ambiente de desktop, apenas com o pequeno e rápido gerenciador de janelas icewm. (Ele é reduzido porque, do contrário, é muito lento, e dessa forma ele supera o GNOME em um hardware muito melhor)

Especificamente, eu tenho instalado os seguintes pacotes: acpi-fakekey acpi-suporte acpi-support-básico acpid pm-utils mas não tem NENHUMA das seguintes (tendo purificado): gnome * kde * systemd * uswsusp uptop laptop-mode-tools hibernate policykit-1

Então, coloco isso em /etc/cron.d/battery_low_check (tudo em uma linha, dividido por legibilidade):

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

É rápido, de baixo uso de recursos, e não depende de outros deamons (se for verdade, ele será ignorado se eles estiverem ativos - veja /usr/share/acpi-support/policy-funcs para detalhes).

O que ele faz: a cada 5 minutos ( */5 - você pode mudar para cada minuto usando apenas * se precisar verificar a bateria com mais frequência), ele pesquisará o status da bateria ( " acpi --battery ") e execute o comando após xargs -ri apenas se a bateria estiver "Descarregando" (ou seja, você não estiver conectado a CA) e o status da bateria for menor que 10% ( " int ($ 2) < 10 " - sinta-se à vontade para ajustá-lo às suas necessidades)

acpi_fakekey 205 enviará por padrão o evento KEY_SUSPEND ACPI (como você pressionou uma tecla no laptop solicitando a suspensão), que fará o que normalmente faz por você (configurado em /etc/default/acpi-support ) - para mim ele hiberna disco.

Você poderia usar outro comando em vez de acpi_fakekey 205 : como hibernate (do pacote hibernate), s2disk ou s2mem (do pacote uswsusp), pm-suspend-hybrid (do pacote pm-utils), etc. .

BTW, os números de chave mágica como KEY_SUSPEND = 205 acima são definidos em /usr/share/acpi-support/key-constants (outro interessante é provavelmente KEY_SLEEP = 142 )

    
por 24.01.2017 / 02:15
0

Eu gosto dessa solução, que é inspirada em parte por outras respostas: link , ou seja, o script batterynotif(uname).sh .

Veja o script aqui: link

Para meu próprio uso, alterei o script para inserir hibernação-suspensão em vez de desligar, usando o comando systemctl hybrid-sleep . (O espaço de troca é necessário por esta opção.)

    
por 04.04.2017 / 23:11