Come faccio a far dormire il mio laptop quando raggiunge una soglia di batteria scarica?


24

Sto usando Ubuntu, ma ho i3 come gestore delle finestre invece di un ambiente desktop.

Quando la mia batteria raggiunge lo 0%, il computer si spegne improvvisamente, nessun avviso o altro.

Esiste un semplice script o configurazione che posso impostare in modo che vada a dormire, diciamo al 4% della batteria?

Risposte:


12

Ecco un piccolo script che verifica il livello della batteria e chiama un comando personalizzato, qui pm-hibernate, nel caso in cui il livello della batteria sia inferiore a una determinata soglia.

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

È una sceneggiatura molto semplice, ma penso che tu abbia l'idea e possa adattarla facilmente alle tue esigenze. Il percorso per il livello della batteria potrebbe essere diverso sul tuo sistema. Un po 'più portatile sarebbe probabilmente usare qualcosa di simile acpi | cut -f2 -d,per ottenere il livello della batteria. Questo script può essere programmato da cron per essere eseguito ogni minuto. Modifica il tuo crontab con crontab -ee aggiungi lo script:

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

Un'altra soluzione sarebbe quella di installare un ambiente desktop come Gnome o Xfce (e cambiare il gestore delle finestre in i3). Entrambi gli ambienti destop citati dispongono di demoni di gestione dell'alimentazione che si occupano di spegnere il computer. Ma presumo che tu non li usi deliberatamente e cerchi una soluzione più minimalista.


Ho provato a correre sleepd -b 40e non è successo niente dopo il 40%. Ho anche provato sudo sleepd -b 40 -s pm-suspende non succede nulla ...
o_o_o--

@NoamGagliardi Confermato, non funziona neanche qui. Inoltre il pacchetto sembra non mantenuto. Provo se trovo un'alternativa migliore e aggiorno la mia risposta, altrimenti la cancellerò.
Marco

(TIL " cut".) La sceneggiatura funziona! Ho acpi | cut -f2 -d, | cut -f1 d%- Leggerò di cron per farlo funzionare da solo. Grazie!
o_o_o--

Non ho /sys/devices/platform/smapi/directory. Dove posso trovare la percentuale rimanente di carica della batteria? Sto usando il kernel personalizzato 3.10
Martin Vegter,

2
@MartinVegter Dipende dal tuo hardware, puoi provare /sys/class/power_supply/BAT0/capacity. Altrimenti usa il acpicomando.
Marco,

6

Invece di hackerare i tuoi script e se stai usando Ubuntu come suggerisce il tag, potresti semplicemente installare il pacchetto upower. Dovrebbe essere disponibile su tutti i derivati ​​Debian incluso Ubuntu. Per impostazione predefinita, viene fornito con una configurazione in /etc/UPower/UPower.confcui si attiva la sospensione ibrida quando il livello della batteria raggiunge valori critici. L'impostazione predefinita per il livello critico è 2%.

Per gli utenti di altre distribuzioni, le voci rilevanti per /etc/UPower/UPower.confsono:

PercentageAction=2
CriticalPowerAction=HybridSleep

È inoltre possibile utilizzare TimeActioninsieme UsePercentageForPolicy=falseper consentire l'esecuzione dell'azione solo dopo che è rimasto il tempo specificato:

TimeAction=120

I valori validi per CriticalPowerActionsono PowerOff, Hibernatee HybridSleep. Se HybridSleep è impostato ma non disponibile, verrà utilizzato l'ibernazione. Se l'ibernazione è impostata ma non disponibile, verrà utilizzato PowerOff.

Il vantaggio di HybridSleep è che, oltre a scrivere la memoria nell'area di scambio, sospende il sistema. La sospensione consumerà comunque un po 'di batteria, ma se torni prima che la batteria si esaurisca, puoi riprendere molto più rapidamente da un sistema sospeso che da uno ibernato. Nel caso in cui la batteria si esaurisca prima di tornare a una presa di corrente, è possibile riprendere il sistema dal letargo una volta ripristinata l'alimentazione.


Nota: penso che HybridSleeprichieda uno spazio di scambio.

2
@cipricus è corretto ma upower sceglierà con grazia di spegnere la macchina invece se non è in letargo.
Jos

2

La risposta attualmente accettata è ottima, ma un po 'datata per Ubuntu 16.04:

  • I comandi per ottenere lo stato della batteria sono cambiati.
  • Le variabili di ambiente richieste per il funzionamento di notifica-invio sono state modificate .
  • Lo script fornito non funziona più dall'utente cron poiché l'ibernazione richiede root.
  • systemctl hibernateè preferito sopra pm-hibernate.

Quindi, ecco lo script che 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

Le variabili d'ambiente necessarie per notify-sendfunzionare sono create usando questo 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

Questo file deve essere eseguito all'avvio (può essere eseguito utilizzando qualsiasi metodo di tua scelta; utilizzo le applicazioni di avvio integrate di Ubuntu ).

Nota: sudo systemctl hibernate potrebbe non funzionare da cron. Seguire questo per risolverlo.


0

Esistono molti modi in cui può essere implementato, in quanto esistono diversi schemi di gestione del potere implementati a seconda di ciò che è stato installato.

Questo semplice funziona per me su Debian Jessie minimalista senza alcun ambiente desktop, solo con il window manager icewm piccolo e veloce. (Viene ridotto perché è troppo lento altrimenti, e in questo modo supera GNOME su hardware molto migliore)

In particolare, ho installato i seguenti pacchetti: acpi acpi-fakekey acpi-support acpi-support-base acpid pm-utils ma ho NESSUNO dei seguenti (dopo averli eliminati): gnome * kde * systemd * uswsusp upower laptop-mode-tools ibernare policykit-1

Quindi l'ho appena inserito /etc/cron.d/battery_low_check(tutto in una riga, diviso per leggibilità):

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

È rapido, a basso consumo di risorse e non dipende da altri demoni (in realtà, verrà ignorato se sono attivi - vedi /usr/share/acpi-support/policy-funcsper i dettagli).

Cosa fa: ogni 5 minuti ( */5- puoi passare a ogni minuto semplicemente usando *se ne hai bisogno per controllare la batteria più spesso) controllerà lo stato della batteria (" acpi --battery ") ed eseguirà il comando xargs -risolo se la batteria è " Scarico "(ovvero, non sei collegato a CA) e lo stato della batteria è inferiore a 10%(" int ($ 2) <10 "- sentiti libero di sintonizzarti sulle tue esigenze)

acpi_fakekey 205per impostazione predefinita invierà un KEY_SUSPENDevento ACPI (come se tu avessi premuto un tasto sul laptop che richiede la sospensione), che poi farà tutto ciò che di solito fa per te (configurato in /etc/default/acpi-support) - per me va in letargo su disco.

È possibile utilizzare altri comandi invece acpi_fakekey 205ovviamente: like hibernate(dal pacchetto hibernate) s2disko s2mem(dal pacchetto uswsusp), pm-suspend-hybrid(dal pacchetto pm-utils) ecc.

A proposito, i numeri di chiave magica come KEY_SUSPEND = 205 sopra sono definiti in /usr/share/acpi-support/key-constants(l'altro interessante è probabilmente KEY_SLEEP = 142 )


sembra molto carino! ma potrebbe essere usato con systemd timer invece di cron? (esempio qui ) Sono su Solus OS in cui cron è assente.

@cipricus Credo di si, ma evito systemd, quindi non posso fare un esempio. Mi sembra di ricordare che systemd abbia i propri gestori di potenza ACPI, quindi se sei bloccato con systemd probabilmente vorrai evitare di scontrarti con quello
Matija Nalis

grazie, ho trovato un'alternativa che coinvolge uname: github.com/jerrinfrncs/batterynotif/blob/master/…

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.