编写要在恢复时执行的 systemd 服务

编写要在恢复时执行的 systemd 服务

我的戴尔笔记本电脑受到内核 3.14 的错误。作为解决方法,我编写了一个简单的脚本

/usr/bin/亮度修复:

#!/bin/bash

echo 0 > /sys/class/backlight/intel_backlight/brightnes

(并使其可执行chmod +x /usr/bin/brightness-fix:)

以及一个在启动时调用它的 systemd 服务:

/etc/systemd/system/brightness-fix.service

[Unit]
Description=Fixes intel backlight control with Kernel 3.14

[Service]
Type=forking
ExecStart=/usr/bin/brightness-fix
TimeoutSec=0
StandardOutput=syslog
#RemainAfterExit=yes
#SysVStartPriority=99

[Install]
WantedBy=multi-user.target

并启用:systemctl enable /etc/systemd/system/brightness-fix.service

这就像一个魅力,我可以根据需要控制我的显示器亮度。当笔记本电脑进入睡眠模式后恢复时(例如,关闭笔记本电脑边缘时),问题就出现了:亮度控制不再起作用,除非我手动执行上面的第一个脚本:/usr/bin/brightness-fix

如何创建另一个像上面我的那样的 systemd 服务以在恢复时执行?

编辑: 根据下面的评论我已经修改了brightness-fix.service这样的:

[Unit]
Description=Fixes intel backlight control with Kernel 3.14

[Service]
Type=oneshot
ExecStart=/usr/local/bin/brightness-fix
TimeoutSec=0
StandardOutput=syslog

[Install]
WantedBy=multi-user.target sleep.target

我还添加echo "$1 $2" > /home/luca/br.log到我的脚本中以检查它是否实际执行。该脚本实际上也在resume( post suspend)处执行,但没有任何效果(背光为100%且无法更改)。我也尝试过记录$DISPLAY$USER并且在恢复时,它们是空的。所以我的猜测是从睡眠中醒来时脚本执行得太早了。有什么提示吗?

答案1

我知道这是一个老问题,但以下单元文件可以让我在从睡眠状态恢复时运行脚本:

[Unit]
Description=<your description>
After=suspend.target

[Service]
User=root
Type=oneshot
ExecStart=<your script here>
TimeoutSec=0
StandardOutput=syslog

[Install]
WantedBy=suspend.target

我相信正是它After=suspend.target使其在恢复时运行,而不是在计算机进入睡眠状态时运行。

答案2

作为编写和启用单元文件的替代方法,您还可以将 shell 脚本(或脚本的符号链接)放入/lib/systemd/system-sleep/.

它将在睡眠/休眠之前和恢复时调用。

man systemd-suspend.service:

在进入系统挂起和/或休眠之前,systemd-suspend.service(以及其他提到的单元)将运行 /usr/lib/systemd/system-sleep/ 中的所有可执行文件,并向它们传递两个参数。第一个参数为“pre”,第二个参数为“挂起”、“休眠”或“混合睡眠”,具体取决于所选操作。在离开系统挂起和/或休眠状态后,立即运行相同的可执行文件,但第一个参数现在是“post”。该目录中的所有可执行文件都是并行执行的,并且直到所有可执行文件都完成后才会继续执行该操作。

用这个测试一下:

#!/bin/sh

# This file (or a link to it) must be in /lib/systemd/system-sleep/

logger -t "test" "\$0=$0, \$1=$1, \$2=$2"

答案3

mivk 的答案的后续内容,其中我避免使用新的单元文件进行处理(请参阅我的问题如何对笔记本电脑盖子事件做出反应?)。这是我的解决方案;这不是 100% 简单()因为系统从睡眠状态出来时不稳定:

在我的 Fedora 26 机器上,我在此处放置了一个符号链接:/usr/lib/systemd/system-sleep/sleepyhead指向此处:/root/bin/sleepyhead,其中包含:

#!/bin/sh
## This file (or a link to it) must be in /lib/systemd/system-sleep/

# This is called when the lid is closed, as follows:
# $0=/usr/lib/systemd/system-sleep/sleepyhead, $1=pre, $2=suspend
# ...and when the lid is opened, as follows:
# $0=/usr/lib/systemd/system-sleep/sleepyhead, $1=post, $2=suspend


touch /tmp/sleepyrun
logger -t "sleepyhead" "Start: \$1=$1, \$2=$2"
if [ "$1" = "post" ] ; then
    action="RUN trackpoint"
    bash /root/bin/trackpoint >/tmp/trackpoint-run 2>&1
else
    action="NO ACTION"
fi
logger -t "sleepyhead" "${action}: " "\$1=$1, \$2=$2"

脚本/root/bin/trackpoint如下。请注意,第一次睡眠至关重要。每次打开盖子时都会设置该设备,因此一开始并不存在。如果我尝试做除睡眠之外的任何事情,“sleepyhead”脚本需要很长时间才能退出,并且我的指针将被冻结至少 60 秒。此外,请注意,您不能将上面的/root/bin/trackpoint脚本置于后台sleepyhead。如果这样做,进程将在sleepyhead退出时被终止。

#!/bin/bash
# This is /root/bin/trackpoint

echo "Start $0"
date

found=false
dir=""
# dirlist can look like:
# /sys/devices/platform/i8042/serio1/serio25/speed
# /sys/devices/platform/i8042/serio1/serio24/speed
# ...the older one appears to get cleaned a little later.

sleep 1 # If I don't put this in here, my pointer locks up for a really long time...
for i in 1 2 3 4; do
    speedfiles=$(find /sys/devices/platform/i8042 -name speed) # There may be multiple speed files at this point.
    [ -z "$speedfiles" ] && { sleep 1; continue; }
    dirlist=$(dirname $speedfiles)
    printf "Speed file(s) at $(find /sys/devices/platform/i8042 -name speed | tail -1) \n"
    # All this remaking of the path is here because the filenames change with
    # every resume, and what's bigger: 9 or 10? ...Depends if you're
    # lexicographical or numerical. We need to always be numerical.
    largest_number="$(echo $dirlist | tr ' ' '\n' | sed -e 's/.*serio//' | sort -n | tail -1)"
    dir="$(echo $dirlist | tr ' ' '\n' | egrep serio${largest_number}\$ )"
    echo "Dir is $dir number is $largest_number" 
    [ -n "$dir" ] && found=true && break
done
$found || exit 1


date
echo -n 4 > $dir/inertia
echo -n 220 > $dir/sensitivity
echo -n 128 > $dir/speed
date
echo "Done $0"

答案4

仅供记录:

如果您需要以 root 身份执行某些操作,则还需要指定用户。
并且WantedBy=multi-user.target让它在系统启动时自动运行。

StandardOutput=syslog

已弃用,可以安全地省略。
StandardOutput=journal是新的默认值。

下面是在启动时和从待机状态返回时将音量静音的示例:

[Unit]
Description=Mute Audio on Startup and on resume from standby
After=sleep.target

[Service]
User=root
Type=oneshot
ExecStart=/usr/bin/amixer -D pulse sset Master mute
TimeoutSec=0

[Install]
WantedBy=multi-user.target sleep.target

相关内容