Вопрос или проблема
Я провел эксперимент. Я использовал K3b для записи iso на CD-RW. Во время этого процесса я выполнил systemctl suspend
.
Компьютер действительно ушел в спящий режим.
Я неправильно понимаю systemd-inhibit
?
Я посмотрел на это и не уверен, может ли это помочь.
Как временно запретить спящий режим?
systemd-inhibit может быть использован для выполнения программы с блокировкой отключения, спящего режима или бездействия.
Блокировка будет получена перед выполнением указанной командной строки и освобождена после.
Блокировки-инхибиторы могут использоваться для блокировки или задержки запросов на спящий режим и отключение системы от пользователя, а также для автоматической обработки бездействия ОС. Это полезно для предотвращения спящего режима системы во время записи оптического диска или аналогичных операций, которые не должны прерываться.
У меня была такая же проблема — после вызова команды, завернутой в systemd-inhibit
, мой ноутбук успешно вошел в спящий режим. Я не нашел решения этой проблемы, но у меня есть хороший обходной путь. (Я использую archlinux, но, я полагаю, это должно работать в большинстве случаев.)
Основная идея состоит в обертке основной службы (бинарного файла или скрипта), реализующей функциональность сна.
1. Найдите основную службу
$ systemctl status systemd-suspend.service
○ systemd-suspend.service - System Suspend
Loaded: loaded (/usr/lib/systemd/system/systemd-suspend.service; static)
Проверьте содержимое /usr/lib/systemd/system/systemd-suspend.service
$ cat /usr/lib/systemd/system/systemd-suspend.service
...
[Service]
Type=oneshot
ExecStart=/usr/lib/systemd/systemd-sleep suspend
И победителем является /usr/lib/systemd/systemd-sleep.
Обратите внимание, что он принимает один аргумент, поэтому обертка-скрипт не должна его терять. В качестве бонуса мы исправим все другие режимы (poweroff и hibernate) в одном месте.
$ file /usr/lib/systemd/systemd-sleep
/usr/lib/systemd/systemd-sleep: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=fa6da37bf95f4a7255909a8e18fecbc1f3910acc, for GNU/Linux 4.4.0, stripped
2. Переместите его
sudo mv /usr/lib/systemd/systemd-sleep /usr/lib/systemd/systemd-sleep.bin
3. Создайте обертку-скрипт
Например, в моем .bash_aliases у меня есть:
alias lxcexport="systemd-inhibit lxc image export"
. Экспорт, вызванный этой псевдокомандой, должен блокировать сервис сна, пока lxc не завершит экспорт контейнера.
В отчете systemd-inhibit
указывается, что он заблокирован командой systemd-inhibit:
$ systemd-inhibit --list --no-pager
WHO UID USER PID COMM WHAT WHY MODE
...
lxc image export server:container… 1000 cot 868971 systemd-inhibit shutdown:sleep:idle Unknown… block
...
Таким образом, в скрипте-обертке мы задерживаем вызываемое действие сна на заранее определенную задержку (например, 5 секунд), пока systemd-inhibit --list --no-pager --no-legend|grep systemd-inhibit
возвращает ненулевой результат. После освобождения блокировки grep вернет ничего и скрипт продолжит выполнение и вызовет основной бинарный файл службы сна с переданным аргументом.
NB Имейте в виду, что когда это произойдет, это не остановится автоматически при повторной активации пользователя. То есть это будет игнорировать вас.
sudo vi /usr/lib/systemd/systemd-sleep.wrapper
#!/bin/sh
while test -n "$(systemd-inhibit --list --no-pager --no-legend|grep systemd-inhibit)" ; do
printf '.'
sleep 5
done
/usr/lib/systemd/systemd-sleep.bin $1
Сделайте его исполняемым.
sudo chmod +x /usr/lib/systemd/systemd-sleep
Наконец, создайте ссылку на скрипт-обертку. Таким образом, вы не потеряете скрипт-обертку, если запланированное обновление системы перезапишет systemd-sleep.
sudo ln -s /usr/lib/systemd/systemd-sleep.wrapper /usr/lib/systemd/systemd-sleep
В журнале это выглядит примерно так:
May 09 08:54:53 LIVE.ARCH.BOX systemd-logind[798]: The system will suspend now!
May 09 08:54:53 LIVE.ARCH.BOX systemd[1]: Reached target Sleep.
May 09 08:54:53 LIVE.ARCH.BOX systemd[1]: Starting System Suspend…
May 09 08:54:53 LIVE.ARCH.BOX systemd-logind[798]: Operation ‘sleep’ finished.
May 09 08:58:27 LIVE.ARCH.BOX systemd[1545]: snap.lxd.lxc.9a9d4293-449f-4314-91b3-02aca1c4006b.scope: Consumed 4min 39.349s CPU time.
May 09 08:58:29 LIVE.ARCH.BOX systemd-sleep[859442]: …………………………………….
May 09 08:58:29 LIVE.ARCH.BOX systemd-sleep[863081]: Going to suspend…
May 09 08:58:29 LIVE.ARCH.BOX systemd-sleep[863080]: Going to suspend…
May 09 08:58:29 LIVE.ARCH.BOX systemd-sleep.bin[863078]: Entering sleep state ‘suspend’…
May 09 08:58:29 LIVE.ARCH.BOX kernel: PM: suspend entry (deep)
May 09 08:58:29 LIVE.ARCH.BOX kernel: Filesystems sync: 0.487 seconds
СОВЕТ
То же самое можно сделать с pm-utils (но на этот раз я изменил скрипт действия напрямую):
$ which pm-hibernate
/usr/bin/pm-hibernate
10:24:34 [cot@LIVE ~]$ ls -la /usr/bin/pm-hibernate
lrwxrwxrwx 1 root root 31 May 8 2021 /usr/bin/pm-hibernate -> /usr/lib/pm-utils/bin/pm-action
.
$ cat /usr/lib/pm-utils/bin/pm-action
...
command_exists "check_$METHOD" && command_exists "do_$METHOD" || {
log "pm-utils не знает, как $METHOD на этой системе."
exit 1
}
##задержка, если systemd-inhibit была вызвана кем-то
while test -n "$(systemd-inhibit --list --no-pager --no-legend|grep systemd-inhibit)" ; do
printf '.'
sleep 55
done
...
Суть путаницы
Вы привели цитату из руководства systemd-inhibit
. Однако, вы, вероятно, путаетесь, как это должно работать, возможно, из-за формулировки руководства.
В руководстве говорится, что systemd-inhibit
полезен для предотвращения спящего режима системы во время операций, таких как запись оптического диска.
Итак, в то время, когда вы используете K3b (программа записи дисков), вы можете ошибочно ожидать, что система автоматически запрещает спящий режим во время записи.
К сожалению, это не так, как systemd-inhibit
работает по умолчанию. Это не демон, который автоматически обнаруживает и предотвращает сон для всех критических операций. Хотя вы можете быть введены в заблуждение, полагая, что все программы systemd — это демоны, работающие в фоне, systemd-inhibit
— это инструмент командной строки, который позволяет вам как пользователю явно запрещать спящие, отключенные или бездействующие состояния во время выполнения определенной команды.
Другая недопонимание заключается в том, что вы выполнили команду systemd-inhibit после того, как начали K3b. systemd-inhibit
принимает имя программы для запуска, а не идентификатор процесса уже запущенной программы.
Если вы хотите предотвратить спящий режим системы во время работы K3b, вам нужно заранее использовать systemd-inhibit
следующим образом:
systemd-inhibit --what=sleep --who="K3b" --why="Запись ISO" k3b
Эта команда гарантирует, что система не перейдет в спящий режим, пока работает K3b.
Ошибочные ожидания
Если вы запускаете K3b сначала, а затем пытаетесь использовать systemd-inhibit для уже запущенного процесса, это не сработает. Например, следующее неверно:
[неверно] systemd-inhibit --what=sleep --who="K3b" --why="Запись ISO" --pid=
[/неверно]
Это не сработает, потому что systemd-inhibit не поддерживает присоединение к уже существующим процессам.
Аргументы командной строки (из руководства)
--what=
: Указывает, что следует запретить (например,спящий режим
,отключение
,бездействие
). По умолчанию —idle:sleep:shutdown
, если не указано.--who=
: Краткое описание программы, берущей блокировку (по умолчанию используется командная строка).--why=
: Краткое описание причины блокировки (по умолчанию «Неизвестная причина»).--mode=
: Указывает, как применяется блокировка (block
,delay
илиblock-weak
). По умолчанию —block
.
Автоматизация
Хотя systemd-inhibit
– мощный инструмент, он требует ручного вмешательства для эффективной работы. Идеально было бы, чтобы приложения, такие как K3b, решали бы это сами путем программного получения и освобождения блокировок-инхибиторов во время критических операций (например, записи диска). Это обеспечило бы лучший пользовательский опыт и предотвратило бы потерю данных или повреждение оборудования из-за неожиданного перехода в спящий режим системы.
Если бы K3b был разработан для этого, он использовал бы интерфейс D-Bus для автоматического получения и освобождения блокировок-инхибиторов. До тех пор вам необходимо явно использовать systemd-inhibit
, чтобы гарантировать, что критические задачи не будут прерваны переходом в спящий режим системы.
.
Ответ или решение
Теория
systemd-inhibit
— это инструмент командной строки, который позволяет пользователю временно блокировать действия системы, такие как переход в спящий режим или выключение, во время выполнения определенной команды. Цель этого инструмента — предотвратить неожиданные системные действия, которые могут прервать важные процессы, например, запись диска. Однако существует некоторое непонимание того, как systemd-inhibit
работает, особенно среди пользователей, которые ожидают, что он будет автоматически выявлять и блокировать такие действия для всех критических операций.
Пример
Проблема, описанная пользователем, касалась попытки использования systemd-inhibit
для предотвращения перехода системы в спящий режим во время записи ISO-образа на CD-RW диске с помощью K3b. Пользователь запустил K3b, а затем выполнил команду systemctl suspend
, и система ушла в спящий режим, что и вызвало сомнения в корректности понимания работы systemd-inhibit
. Этот инцидент подчеркивает важность корректного использования systemd-inhibit
.
Применение
Для правильной работы systemd-inhibit
необходимо вызвать его перед началом выполнения критичной операции. Например, чтобы предотвратить переход системы в спящий режим во время работы K3b, следует выполнить команду:
systemd-inhibit --what=sleep --who="K3b" --why="Burning an ISO" k3b
Эта команда инициирует запуск K3b под контролем systemd-inhibit
, тем самым гарантируя, что система не перейдет в спящий режим до завершения операции.
Заключение
Важно понимать, что systemd-inhibit
не является сервисом, который автоматически контролирует системные действия для всех программ. Он требует явного использования. Поэтому, для обеспечения безопасности и непрерывности работы определенных приложений, таких как запись дисков, пользователю необходимо заранее планировать использование systemd-inhibit
. Наилучшим решением будет взаимодействие приложений с D-Bus для автоматического управления блокировками, что, в свою очередь, может улучшить пользовательский опыт и предотвратить возможные потери данных.