Приветствую, авантюрист. Продолжаем реализовывать задуманное. Напомню, мы делаем свои GPO политики на Альт Линукс.
Дисклеймер
Я не могу сказать, что я эксперт в данном вопросе. Даже наоборот. Я всего лишь хочу поделиться своим опытом. Рассказать, что у меня получилось и как я к этому пришел. Безусловно, я не утверждаю, что способы и методы, которые я использовал, единственные верные или вообще верные. Наверняка среди комментаторов найдутся истинные профессионалы и поделятся ссылками на правильные и верные методы решения затронутого мной вопроса. Я всегда приветствую диалог
Статьи:
Необходимый уровень знаний
Для качественного понимания материала тебе потребуется хорошее понимание доменных политик и принципов их функционирования. Также необходим опыт написания скриптов на bash и знание основ работы домен-контроллеров. Рекомендуется, хотя и не обязательно, иметь навыки программирования на C++ с использованием фреймворков QT или Python. Кроме того, необходимо уверенно работать с сетевыми дисками в среде Linux.
Постановка задачи
Первая задача — это сделать так, чтобы при входе в систему у любого пользователя происходил запуск нужного нам скрипта. Просто добавиться в автозапуск пользователя мы не можем. Ведь мы не знаем, какие пользователи будут заходить на конкретную машину. Напомню, что у нас реализован домен на Free IPA сервере. А добавлять каждому пользователю вручную необходимые данные в автозапуск — это явно не true решение.
Автозапуск в КДЕ
Итак, при авторизации пользователя нам нужно проверить, есть ли в автозапуске нужный нам скрипт, и если его нет, то добавить. Скрипт будет лежать вот тут /usr/bin/run_my_app.sh
Его нам надо запускать. Первое, что мы делаем, это создаем ярлык вот с таким содержимым.
[Desktop Entry]
Exec=/usr/bin/run_my_app.sh
Icon=dialog-scripts
Name=run_my_app.sh
Type=Application
X-KDE-AutostartScript=true
Ярлык назовем run_my_app.descktop
Далее нам нужно поместить этот ярлык в папку ~/.config/autostart/. Именно туда помещаются ярлыки приложений, которые ты добавляешь в автозапуск. Но как он там окажется сам? Читаем дальше.
Событие авторизации и выхода пользователя из системы.
Теперь самое интересное. Как нам при авторизации пользователя выполнить некие действия? Тут на помощь приходит PAM. Сильно знать, что это такое и как оно работает, не нужно (да я и не знаю). Всё, что нам нужно знать, это то, что в папке /etc/pam.d/ лежат скрипты, которые выполняются в зависимости от способа авторизации пользователя. Методом «тыка» находим, что файл /etc/pam.d/common-login выполняется каждый раз, когда пользователь авторизуется и выходит из системы. Что нам и надо.
Далее в синтаксисе PAM находим вот такую конструкцию
session optional pam_exec.so «ПУТЬ К ФАЙЛУ»
Данная запись означает запустить файл, путь к которому был указан. Первое, что приходит в голову, сделать вот так:
session optional pam_exec.so /bin/bash /usr/bin/run_my_app.sh.
Но тут кроется огромный подводный камень, об который я сломал кучу мизинцев. Дело в том, что запуск тут произойдет на очень ранней стадии загрузки системы и «вне» оболочки. Это значит, что мы не сможем взаимодействовать с интерфейсом и вообще не поймем, загружена ли уже сеть или видит ли уже пользователь графику? Наверно, как-то это всё можно отладить, но я пошел по пути наименьшего сопротивления и здесь добавил наш скрипт /usr/bin/run_my_app.sh, а некую «прослойку», задача которой будет одна-единственная — это проверить наличие в автозапуске у текущего входящего в систему пользователя скрипта /usr/bin/run_my_app.sh. Назовем эту прослойку check_autorun.sh и поместим туда же в /usr/bin/
По итогу файл /etc/pam.d/common-login будет выглядеть примерно вот так
Так. Теперь при каждом входе и выходе ЛЮБОГО пользователя в систему будет запускаться прослойка /usr/bin/check_autorun.sh
Прослойка
Теперь давай разбираться, что должен делать скрипт-прослойка и как мы его реализуем. На самом деле файл /etc/pam.d/common-login вызывается чуток чаще. Например, когда ты набираешь «su -» и входишь в рута, этот файл тоже запускается. Также он срабатывает при работе некоторых системных сервисов, которые запускаются от имени других пользователей. Дабы отфильтровать ненужные срабатывания, воспользуемся переменными $PAM_TYPE, $PAM_USER и $PAM_SERVICE
Вот такой кусочек кода у меня получился в результате проб и ошибок. Теперь лишних срабатываний нашей прослоечки не будет. И она выполнится строго 1 раз при входе пользователя.
Ну а теперь дело за малым: нужно проверить наличие ярлыка в папке автозапуска
if test -f "/home/$PAM_USER/.config/autostart/update_run_my_app.sh.desktop"; then
exit
else
cp /opt/my_app/update_run_my_app.sh.desktop "/home/$PAM_USER/.config/autostart/update_run_my_app.sh.desktop"
fi
Ярлык я предварительно поместил в папку /opt/my_app, именно там и будет лежать в будущем наше основное приложение, для запуска которого мы и проделываем все эти манипуляции.
Итог
Итак. Схема работы нашей системы автозапуска следующая. При входе пользователя в систему срабатывает файл /etc/pam.d/common-login, который вызывает файл-прослойку /usr/bin/check_autorun.sh, которая проверяет наличие в автозапуске у текущего юзера скрипта /usr/bin/run_my_app.sh, который будет запускать нашу основную программу, забегая вперед, не только запускать, но и обновлять. Основная программа, в свою очередь, будет находиться в каталоге /opt/my_app.
Выглядит громоздко, согласен. Но более элегантного решения тут как будто бы нет. Да и каждый элемент четко выполняет свою конкретную задачу, что, по идее, хорошо. В случае какого-либо изменения мы правим один файл и не трогаем другие.
Для быстрой настройки новых ПК я сделал небольшой скрипт-установщик. Он создает нужные каталоги, выдает нужные права, вносит изменения в файл /etc/pam.d/common-login, копирует скрипты /usr/bin/check_autorun.sh и /usr/bin/run_my_app.sh в соответствующие каталоги. Что-то типа такого.
#!/bin/bash
mkdir /opt/my_app
cp ./run_my_app.sh /usr/bin/run_my_app.sh
cp ./check_autorun.sh /usr/bin/check_autorun.sh
echo "session optional pam_exec.so /bin/bash /usr/bin/check_autorun.sh" &>> /etc/pam.d/common-login
cp update_run_my_app.sh.desktop "/home/$USER/.config/autostart/update_run_my_app.sh.desktop"
cp update_run_my_app.sh.desktop /opt/my_app
На самом деле большая часть работы уже сделана. В следующей статье начнем писать наше основное приложение. Удачи, авантбрист.