Bagaimana cara membuat laptop saya tidur ketika mencapai ambang baterai rendah?

24

Saya menggunakan Ubuntu, tetapi saya memiliki i3 sebagai window manager daripada lingkungan desktop.

Ketika baterai saya mencapai 0%, komputer akan mati tiba-tiba, tidak ada peringatan atau apa pun.

Apakah ada skrip atau konfigurasi sederhana yang dapat saya atur sehingga bisa digunakan untuk tidur, katakanlah baterai 4%?

o_o_o--
sumber

Jawaban:

12

Berikut ini adalah skrip kecil yang memeriksa tingkat baterai dan memanggil perintah khusus, di sini pm-hibernate, jika tingkat baterai di bawah batas tertentu.

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

Ini skrip yang sangat sederhana, tetapi saya pikir Anda mendapatkan ide dan dapat dengan mudah menyesuaikannya dengan kebutuhan Anda. Jalur ke level baterai mungkin berbeda pada sistem Anda. Sedikit lebih portabel mungkin akan menggunakan sesuatu seperti acpi | cut -f2 -d,untuk mendapatkan level baterai. Script ini dapat dijadwalkan oleh cron untuk dijalankan setiap menit. Edit crontab Anda dengan crontab -edan tambahkan skrip:

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

Solusi lain adalah memasang lingkungan desktop seperti Gnome atau Xfce (dan ubah window manager Anda menjadi i3). Kedua lingkungan destop yang disebutkan memiliki daemon manajemen daya yang menjaga mematikan komputer. Tapi saya berasumsi Anda sengaja tidak menggunakannya dan mencari solusi yang lebih minimalis.

Marco
sumber
Hm, saya mencoba berlari sleepd -b 40dan tidak ada yang terjadi setelah tanda 40%. Saya juga mencoba sudo sleepd -b 40 -s pm-suspenddan tidak ada yang terjadi ...
o_o_o--
@NoamGagliardi Dikonfirmasi, juga tidak berfungsi di sini. Selain itu paket itu tampaknya tidak terawat. Saya mencoba jika saya dapat menemukan alternatif yang lebih baik dan memperbarui jawaban saya, kalau tidak saya akan menghapusnya.
Marco
(TIL " cut".) Script berfungsi! Saya punya acpi | cut -f2 -d, | cut -f1 d%- saya akan membaca tentang cron untuk menjalankannya sendiri. Terima kasih!
o_o_o--
Saya tidak punya /sys/devices/platform/smapi/direktori. Di mana saya dapat menemukan persentase sisa daya baterai? Saya menggunakan kernel khusus 3.10
Martin Vegter
2
@ MartinVegter Tergantung pada perangkat keras Anda, Anda dapat mencoba /sys/class/power_supply/BAT0/capacity. Kalau tidak gunakan acpiperintah.
Marco
6

Alih-alih meretas skrip Anda sendiri dan jika Anda menggunakan Ubuntu seperti yang disarankan tag, Anda bisa menginstal paket upower. Ini harus tersedia di semua turunan Debian termasuk Ubuntu. Secara default ia datang dengan konfigurasi di /etc/UPower/UPower.confmana mengaktifkan hibrida tidur setelah tingkat baterai mencapai nilai kritis. Default untuk level kritis adalah 2%.

Untuk pengguna distribusi lain, entri yang relevan /etc/UPower/UPower.confadalah:

PercentageAction=2
CriticalPowerAction=HybridSleep

Anda juga dapat menggunakan TimeActionbersama dengan UsePercentageForPolicy=falseuntuk membiarkan tindakan dilakukan setelah hanya waktu yang ditentukan yang tersisa:

TimeAction=120

Nilai yang valid untuk CriticalPowerActionadalah PowerOff, Hibernatedan HybridSleep. Jika HybridSleep diatur tetapi tidak tersedia, Hibernate akan digunakan. Jika Hibernate diatur tetapi tidak tersedia, PowerOff akan digunakan.

Keuntungan dari HybridSleep adalah, bahwa selain menuliskan memori ke dalam area swap Anda, itu juga menunda sistem. Penangguhan masih akan menghabiskan beberapa baterai tetapi jika Anda kembali sebelum baterai habis, Anda dapat jauh lebih cepat melanjutkan dari sistem yang ditangguhkan daripada dari yang hibernasi. Seandainya baterai benar-benar habis sebelum Anda kembali ke soket daya, Anda dapat melanjutkan sistem dari hibernasi setelah Anda memiliki daya lagi.

josch
sumber
Catatan: Saya pikir HybridSleepperlu memiliki ruang swap.
2
@cipricus yang benar tetapi lebih tinggi dengan anggun akan memilih untuk mematikan mesin jika tidak bisa hibernasi.
josch
2

Jawaban yang diterima saat ini bagus, tetapi sedikit ketinggalan jaman untuk Ubuntu 16.04:

  • Perintah untuk mendapatkan status baterai telah berubah.
  • Variabel lingkungan yang diperlukan untuk pemberitahuan-kirim untuk bekerja telah berubah .
  • Skrip yang diberikan di sana tidak lagi berfungsi dari cron pengguna karena hibernate memerlukan root.
  • systemctl hibernatelebih disukai daripada pm-hibernate.

Jadi, inilah skrip yang saya gunakan:

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

Variabel lingkungan yang diperlukan untuk notify-sendbekerja dibuat menggunakan skrip ini :

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

File ini perlu dijalankan pada saat startup (dapat dilakukan dengan menggunakan metode apa pun pilihan Anda; Saya menggunakan Aplikasi Startup bawaan Ubuntu ).

Catatan: sudo systemctl hibernate mungkin tidak berfungsi dari cron. Ikuti ini untuk menyelesaikannya.

Anmol Singh Jaggi
sumber
0

Ada banyak cara yang dapat diterapkan, karena ada banyak skema manajemen daya yang berbeda tergantung pada apa yang telah Anda instal.

Yang sederhana ini berfungsi untuk saya di Debian Jessie minimalis tanpa lingkungan desktop, hanya dengan pengelola jendela icewm kecil dan cepat. (Dipangkas karena terlalu lambat jika tidak, dan cara ini mengungguli GNOME pada perangkat keras yang jauh lebih baik)

Secara khusus, saya telah menginstal paket-paket berikut: acpi acpi-fakekey acpi-support acpi-support-base acpid pm-utils tetapi memiliki NONE dari yang berikut (setelah dibersihkan): gnome * kde * systemd * uswsusp upower laptop-mode-tools hibernate policykit-1

Jadi saya hanya memasukkan ini /etc/cron.d/battery_low_check(semua dalam satu baris, pisah untuk dibaca):

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

Ini cepat, penggunaan sumber daya rendah, dan tidak bergantung pada diaken lain (jika faktanya, ia akan diabaikan jika aktif - lihat /usr/share/acpi-support/policy-funcsdetailnya).

Kegunaan: setiap 5 menit ( */5- Anda dapat mengganti setiap menit hanya dengan menggunakan *jika Anda memerlukannya untuk memeriksa baterai lebih sering) ia akan mengumpulkan status baterai (" acpi --battery ") dan menjalankan perintah setelah xargs -rihanya jika baterai " Pengosongan "(yaitu, Anda tidak terhubung ke AC) dan status baterai kurang dari 10%(" int ($ 2) <10 "- jangan ragu untuk menyesuaikannya dengan kebutuhan Anda)

acpi_fakekey 205akan secara default mengirim KEY_SUSPENDacara ACPI (seperti Anda menekan tombol pada laptop yang meminta penangguhan), yang kemudian akan melakukan apa pun yang biasanya dilakukan untuk Anda (dikonfigurasi dalam /etc/default/acpi-support) - bagi saya itu akan hibernasi ke disk.

Anda dapat menggunakan perintah lain alih-alih acpi_fakekey 205tentu saja: seperti hibernate(dari paket hibernate), s2diskatau s2mem(dari paket uswsusp), pm-suspend-hybrid(dari paket pm-utils) dll.

BTW, angka kunci ajaib seperti KEY_SUSPEND = 205 di atas didefinisikan /usr/share/acpi-support/key-constants(yang menarik lainnya mungkin KEY_SLEEP = 142 )

Matija Nalis
sumber
sepertinya sangat bagus! tetapi dapatkah itu digunakan dengan systemd timer bukannya cron? (contoh di sini ) Saya menggunakan Solus OS di mana cron tidak ada.
@cipricus Saya kira begitu, tapi saya menghindari systemd jadi tidak bisa memberikan contoh. Sepertinya saya ingat systemd memiliki power handler ACPI sendiri, jadi jika Anda terjebak dengan systemd Anda mungkin ingin menghindari bentrok dengan itu
Matija Nalis
terima kasih, saya telah menemukan alternatif yang melibatkan uname: github.com/jerrinfrncs/batterynotif/blob/master/…