Найти тему
Easy Linux - о Linux просто

Выполнение действий при выключении компьютера на Alt linux рабочая станция K

Приветствую авантюрист. Сегодня я хочу рассказать об одной интересной задаче, в решении которой мне не смогли подсказать ни участники нашего сообщества, ни служба поддержки Alt Linux ни участники других тематических сообществ. Я прекрасно понимаю что я не умею искать, но в сети найти годную информацию для решения задачи так же не удалось.

Итак, задача. При завершении пользователем работы предложить выполнить некий ряд обслуживающих действий. Дать пользователю выбор, все таки просто выключить ПК или выполнить сервисные задачи и уже потом ПК выключиться сам. Это должно делаться в графической сессии. Я должен отреагировать на выключение, отменить его и запустить свою программу или скрипт, не давая операционной системе завершить графическую сессию. Все это работает на Альт Линукс рабочая станция К.

На первый взгляд звучит довольно просто, но начав гуглить и собирать информацию я понял, что будет не легко. В KDE можно запустить скрипт при выключении, но он срабатывает слишком поздно, когда графическая сессия уже завершилась. Подсистема inhibit так же отрабатывает когда графическое окружение уже полностью выгружено. Есть PAM. И в теории там можно выполнить скрипт при некоторых событиях. Но я не смог получать нужного эффекта, по большей части этот инструмент так же отрабатывает после выхода пользователя из графической сессии.

Но ведь мы знаем что эта задача выполнима. К примеру, VirtualBox. Если мы попробуем выключить ПК при хотя бы одной работающей гостевой системе, то мы увидим уведомление что VirtualBox не дает завершить работу системе. А значит какой то механизм есть.

Прежде чем выложить все карты на стол, я хочу уточнить, что я не являюсь ни разработчиком, ни программистом и очень слабо разбираюсь в архитектуре операционных систем. Это важно, потому что решение этой задачи кажется простым для опытных специалистов, которые варятся в разработке. Однако, когда я обращался за помощью на тематических форумах и к технической поддержке Alt Linux, мне отказали. Пришлось искать решение самому.

Как оказалось, для отмены выключения необходимо взаимодействовать с сессионным менеджером. Проще всего наладить это взаимодействие через системные вызовы. Для этого надо написать небольшую программу. Что я и сделал. Я написал небольшую программку для теста на QT создающее одно видимое окно.

Самое просто что мы можем сделать это запретить закрывать окно программы. Для этого достаточно переопределить событие closeEvent главного окна.

void MainWindow::closeEvent(QCloseEvent *event) {
event->ignore();

}

Теперь, при нажатии на кнопку закрыть окно(крестик) не будет ничего происходить . При выключении компьютера система так же не сможет закрыть окно и не сможет завершиться. В целом то что нам и надо. Мы отслеживаем событие выключения и отменяем его. Но наше окно всегда должно быть видимо. А это не очень удобно. Хотелось бы просто тихо висеть в трее или вообще нигде не отсвечивать.

Если копаться дальше то можно найти следующую информацию. При выключении операционная система уведомляет все приложения и дает им время для завершения своих задач. Событие это можно так же обработать и соответствующим образом отреагировать. Называется оно commitData

void MainWindow::commitData(QSessionManager& manager){

// Говорим операционной системе что мы не хотим выключаться
// и делаем тут что захотим
manager.cancel();

}

И не забываем словить сигнал

connect(qApp,&QGuiApplication::commitDataRequest,this,&MainWindow::commitData);

Собственно вот и все. manager.cancel() скажет сессионному менеджеру что выключать ПК нельзя и мы увидим соответствующее сообщение

Окно теперь можно полностью скрыть, дабы оно не мешало. После попытки выключить ПК мы можем открыть любые окна, запускать процессы, выводить диалоги, выстроить любую логику работы и взаимодействия. После этого можем самостоятельно выключить компьютер когда нам будет это нужно.

Надеюсь эта информация кому-нибудь будет полезна.