Làm cách nào để làm cho máy tính xách tay của tôi ngủ khi nó đạt đến ngưỡng pin yếu?


24

Tôi đang sử dụng Ubuntu, nhưng tôi có i3 làm trình quản lý cửa sổ thay vì môi trường máy tính để bàn.

Khi pin của tôi đạt 0%, máy tính sẽ đột ngột tắt, không có cảnh báo hay bất cứ điều gì.

Có một kịch bản hoặc cấu hình đơn giản nào tôi có thể thiết lập để nó đi vào lúc ngủ, giả sử pin 4%?

Câu trả lời:


12

Đây là một đoạn script nhỏ kiểm tra mức pin và gọi lệnh tùy chỉnh, ở đây pm-hibernate, trong trường hợp mức pin dưới một ngưỡng nhất định.

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

Đó là một kịch bản rất đơn giản, nhưng tôi nghĩ bạn có ý tưởng và có thể dễ dàng điều chỉnh nó theo nhu cầu của bạn. Đường dẫn đến mức pin có thể khác trên hệ thống của bạn. Một chút di động hơn có lẽ sẽ là sử dụng một cái gì đó như acpi | cut -f2 -d,để có được mức pin. Kịch bản này có thể được lên lịch bởi cron để chạy mỗi phút. Chỉnh sửa crontab của bạn với crontab -evà thêm tập lệnh:

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

Một giải pháp khác là cài đặt môi trường máy tính để bàn như Gnome hoặc Xfce (và thay đổi trình quản lý cửa sổ của bạn thành i3). Cả hai môi trường định mệnh được đề cập đều có trình quản lý năng lượng, đảm nhiệm việc tắt nguồn máy tính. Nhưng tôi cho rằng bạn cố tình không sử dụng chúng và đang tìm kiếm một giải pháp tối giản hơn.


Hừm, tôi đã thử chạy sleepd -b 40và không có gì xảy ra sau mốc 40%. Tôi cũng đã thử sudo sleepd -b 40 -s pm-suspendvà không có gì xảy ra ...
o_o_o--

@NoamGagliardi Xác nhận, nó cũng không hoạt động ở đây. Hơn nữa, gói dường như không rõ ràng. Tôi cố gắng nếu tôi có thể tìm một giải pháp thay thế tốt hơn và cập nhật câu trả lời của mình, nếu không tôi sẽ xóa nó.
Marco

(TIL " cut".) Kịch bản hoạt động! Tôi có acpi | cut -f2 -d, | cut -f1 d%- Tôi sẽ đọc về cron để tự chạy. Cảm ơn!
o_o_o--

Tôi không có /sys/devices/platform/smapi/thư mục. Tôi có thể tìm phần trăm pin còn lại ở đâu? Tôi đang sử dụng kernel tùy chỉnh 3.10
Martin Vegter

2
@MartinVegter Nó phụ thuộc vào phần cứng của bạn, bạn có thể thử /sys/class/power_supply/BAT0/capacity. Nếu không thì sử dụng acpilệnh.
Marco

6

Thay vì hack các tập lệnh của riêng bạn và nếu bạn đang sử dụng Ubuntu như thẻ gợi ý, bạn có thể chỉ cần cài đặt gói upower. Nó nên có sẵn trên tất cả các dẫn xuất Debian bao gồm Ubuntu. Theo mặc định, nó đi kèm với một cấu hình trong /etc/UPower/UPower.confđó kích hoạt chế độ ngủ lai khi mức pin đạt đến các giá trị quan trọng. Mặc định cho mức độ quan trọng là 2%.

Đối với người dùng các bản phân phối khác, các mục liên quan cho /etc/UPower/UPower.conf:

PercentageAction=2
CriticalPowerAction=HybridSleep

Bạn cũng có thể sử dụng TimeActioncùng với UsePercentageForPolicy=falseđể cho phép hành động được thực hiện khi chỉ còn lại thời gian được chỉ định:

TimeAction=120

Các giá trị hợp lệ CriticalPowerActionPowerOff, HibernateHybridSleep. Nếu HybridS ngủ được đặt nhưng không khả dụng, Hibernate sẽ được sử dụng. Nếu Hibernate được đặt nhưng không khả dụng, PowerPack sẽ được sử dụng.

Ưu điểm của HybridS ngủ là, ngoài việc ghi bộ nhớ vào vùng trao đổi của bạn, nó sẽ tạm dừng hệ thống. Tạm dừng vẫn sẽ tiêu thụ một số pin nhưng nếu bạn quay lại trước khi hết pin, bạn có thể nhanh chóng khôi phục lại từ hệ thống bị treo hơn là từ chế độ ngủ đông. Trong trường hợp pin hết trước khi bạn quay trở lại ổ cắm điện, bạn có thể khôi phục hệ thống từ chế độ ngủ đông sau khi bạn có điện trở lại.


Lưu ý: Tôi nghĩ HybridSleepyêu cầu phải có một không gian trao đổi.

2
@cipricus là chính xác nhưng upower sẽ duyên dáng chọn tắt máy thay vì nếu nó không thể ngủ đông.
josch

2

Câu trả lời hiện được chấp nhận là rất tốt, nhưng hơi lỗi thời đối với Ubuntu 16.04:

  • Các lệnh để có được trạng thái pin đã thay đổi.
  • Các biến môi trường cần thiết để thông báo-gửi đến công việc đã thay đổi .
  • Tập lệnh được cung cấp ở đó không còn hoạt động từ người dùng cron vì hibernate yêu cầu root.
  • systemctl hibernateđược ưa thích hơn pm-hibernate.

Vì vậy, đây là kịch bản tôi sử dụng:

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

Các biến môi trường cần thiết notify-sendđể làm việc được tạo bằng tập lệnh này :

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

Tệp này cần chạy khi khởi động (có thể được thực hiện bằng bất kỳ phương pháp nào bạn chọn; tôi sử dụng Ứng dụng khởi động dựng sẵn của Ubuntu ).

Lưu ý: sudo systemctl hibernate có thể không hoạt động từ cron. Thực hiện theo điều này để giải quyết nó.


0

Có nhiều cách nó có thể được thực hiện, vì có nhiều cách quản lý năng lượng khác nhau được thực hiện tùy thuộc vào những gì bạn đã cài đặt.

Công cụ đơn giản này hoạt động với tôi trên Debian Jessie tối giản mà không cần bất kỳ môi trường máy tính để bàn nào, chỉ với trình quản lý cửa sổ icewm nhỏ và nhanh. (Nó được cắt giảm vì cách khác quá chậm, và cách này vượt trội hơn so với Gnome trên phần cứng tốt hơn nhiều)

Cụ thể, tôi đã cài đặt các gói sau: acpi acpi-fakekey acpi-support acpi-support-base acpid pm-utils nhưng có NONE của những điều sau đây (đã thanh trừng chúng): gnome * kde * systemd * uswsusp upower laptop-mode-tools bộ chính sách ngủ đông-1

Vì vậy, tôi chỉ cần đặt cái này vào /etc/cron.d/battery_low_check(tất cả trong một dòng, được chia để dễ đọc):

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

Nó nhanh chóng, sử dụng ít tài nguyên và không phụ thuộc vào các deamon khác (nếu thực tế, nó sẽ bị bỏ qua nếu chúng hoạt động - xem /usr/share/acpi-support/policy-funcschi tiết).

Nó hoạt động như thế nào: cứ sau 5 phút ( */5- bạn có thể thay đổi thành mỗi phút chỉ bằng cách sử dụng *nếu bạn cần kiểm tra pin thường xuyên hơn), nó sẽ thăm dò tình trạng pin (" acpi --battery ") và thực hiện lệnh chỉ sau khi xargs -ripin là " Xả "(nghĩa là bạn không được kết nối với AC) và trạng thái pin nhỏ hơn 10%(" int ($ 2) <10 "- thoải mái điều chỉnh theo nhu cầu của bạn)

acpi_fakekey 205theo mặc định sẽ gửi KEY_SUSPENDsự kiện ACPI (như bạn đã nhấn một phím trên máy tính xách tay yêu cầu tạm dừng), sau đó sẽ làm bất cứ điều gì nó thường làm cho bạn (được định cấu hình /etc/default/acpi-support) - đối với tôi, nó ngủ đông vào đĩa.

Tất nhiên, bạn có thể sử dụng lệnh khác thay vì acpi_fakekey 205: như hibernate(từ gói hibernate) s2diskhoặc s2mem(từ gói uswsusp), pm-suspend-hybrid(từ gói pm-utils), v.v.

BTW, các số khóa ma thuật như KEY_SUSPEND = 205 ở trên được xác định trong /usr/share/acpi-support/key-constants(một số thú vị khác có lẽ là KEY_SLEEP = 142 )


Điều đó có vẻ rất tốt đẹp! Nhưng điều đó có thể được sử dụng với bộ đếm thời gian systemd thay vì cron không? (ví dụ ở đây ) Tôi đang dùng Solus OS, nơi cron vắng mặt.

@cipricus Tôi đoán vậy, nhưng tôi tránh systemd nên không thể đưa ra ví dụ. Tôi dường như nhớ lại systemd có trình xử lý năng lượng ACPI của riêng nó, vì vậy nếu bạn bị mắc kẹt với systemd, có lẽ bạn sẽ muốn tránh đụng độ với điều đó
Matija Nalis

cảm ơn, tôi đã tìm thấy một giải pháp thay thế liên quan đến uname: github.com/jerrinfrncs/batterynotif/blob/master/

0

Tôi thích giải pháp này, một phần được lấy cảm hứng từ các câu trả lời khác: https://github.com/jerrinfrncs/batterynotif , cụ thể là kịch bản batterynotif(uname).sh.

Xem tập lệnh tại đây: https://github.com/jerrinfrncs/batterynotif/blob/master/batterynotif%28uname%29.sh

Để sử dụng riêng, tôi đã thay đổi tập lệnh để vào chế độ ngủ lai thay vì tắt máy, bằng cách sử dụng lệnh systemctl hybrid-sleep. (Không gian hoán đổi là cần thiết bởi tùy chọn này.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.