Имитация динамических обоев из macOS штатными средствами Linux-систем
Принцип их работы весьма прост. Основан он на способности оконных менеджеров (WM) многих популярных окружений рабочего стола (DE) отслеживать изменения выбранного файла обоев.
В качестве обоев устанавливается только один файл картинки. Используемый файл обоев является символической ссылкой на другую картинку. Ступенчатая "динамичность" обоев обеспечивается заменой картинки-ссылки на новую в нужные моменты времени. В эти же моменты WM замечает изменение файла обоев и обновляет картинку.
Таким образом, WM постоянно работает с одним и тем же файлом-картинкой, а вся логика работы обеспечивается обычным сценарием командной строки и простыми файловыми операциями.
Предыстория создания
Концепцию динамических обоев подглядел ещё в macOS Mojave. Сразу захотел себе такие же.
Что требовалось от обоев:
- смена соответственно времени дня,
- возможность точного задания времени смены обоев,
- минимум внешних зависимостей,
- автономная работа,
- нечувствительность к перезагрузкам и системным сбоям,
- минимальная нагрузка на систему,
- простота обслуживания и гибкость настройки.
В ходе поисков найдены несколько путей достижения цели:
- Установка сторонних программ. Мало где поддерживается точное задание времени, тянутся внешние зависимости, и что-то постоянно будет висеть в фоне.
- Видеообои или gif. Сложно и ресурсоёмко.
- XML-слайдшоу для GNOME. Основан на периодичном отсчёте интервалов в секундах от 11.02.2014. Способ немного топорный и заточен под среду GNOME и её fork'и. Для другого набора обоев придётся заново пересчитывать секунды.
- Взять за основу готовый набор обоев, а логику работы воплощать самому. Вызов принят :)
Статью пишу как памятку для себя и дань благодарности сообществу Хабра, благодаря которому вырос как специалист в своей сфере.
А у меня заработает?
Ваш WM должен уметь следить за используемым файлом обоев. Это можно легко проверить так:
- Скопируйте какую-нибудь картинку в корень своего домашнего каталога.
- Измените имя картинки на какое-нибудь простое. Например "pic1".
- Назначьте картинку обоями рабочего стола.
- Удалите картинку.
- Скопируйте другую картинку в корень своего домашнего каталога.
- Дайте ей имя удалённой ранее картинки.
- Посмотрите на обои рабочего стола. Если они соответствуют новой картинке, то у вас всё заработает.
- Верните прежние обои.
В ролях
Динамические обои будут использовать 5 штатных утилит Linux-систем:
date
— получение текущего времени;rm
— удаление файлов;ls
— создание ссылок на файлы;сron
— выполнение команд по расписанию;bash
— исполнение стартового сценария обоев.
Ничего дополнительно устанавливать не нужно.
Предостережения для опытных
Нижеследующие инструкции по установке и удалению обоев предполагают, что вы ещё не работали с Crontab в своей системе. Если же вы уже работали c Cron и у вас есть настроенная под себя таблица Cron, то вместо установки или восстановления таблицы просто открывайте её через crontab -e
и добавляйте или убирайте дополнительные строки из приведённого crontab.txt в своей crontab в любом удобном текстовом редакторе.
Для сохранности вашей системы и данных других её пользователей все приведённые ниже команды выполняйте только от имени своего пользователя. Привилегии суперпользователя не требуются.
Установка
1) Создайте папку для обоев:
mkdir $HOME/.mojave_dynamic
2) Загрузите набор обоев и извлеките из полученного архива 16 файлов формата .jpeg в папку .mojave_dynamic
. Для Вашего удобства папка обоев скрыта. Поэтому, если её не видно, включите отображение скрытых файлов (обычно, это Ctrl+h).
Пакет обоев любезно предоставлен всем желающим пользователем Reddit randybruder.
3) Создайте картинку-ссылку в папке .mojave_dynamic:
ln -s $HOME/.mojave_dynamic/mojave_dynamic_1.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
4) Создайте в той же папке обычный текстовый файл:
touch $HOME/.mojave_dynamic/crontab.txt
Скопируйте в него текст из-под спойлера, оставьте после него пустую строку и сохраните:
# Динамические обои
# Установка обоев после запуска системы
@reboot bash $HOME/.mojave_dynamic/mojave_dynamic_init.sh
# Смена обоев по расписанию
# Справка по формату файла: https://www.opennet.ru/man.shtml?topic=crontab&category=8&russian=0
# 6:00 №1
0 6 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_1.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 6:30 №2
30 6 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_2.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 7:00 №3
0 7 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_3.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 7:30 №4
30 7 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_4.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 8:00 №5
0 8 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_5.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 10:30 №6
30 10 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_6.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 13:00 №7
0 13 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_7.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 15:30 №8
30 15 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_8.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 18:00 №9
0 18 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_9.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 18:30 №10
30 18 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_10.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 19:00 №11
0 19 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_11.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 19:30 №12
30 19 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_12.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 20:00 №13
0 20 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_13.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 22:30 №14
30 22 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_14.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 01:00 №15
0 1 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_15.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
# 03:30 №16
30 3 * * * rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg ; ln -s $HOME/.mojave_dynamic/mojave_dynamic_16.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg
Пустая строка в конце файла должна быть обязательно. Иначе на следующем шаге Crontab напомнит вам об этом.
Сразу после старта системы Сron запускает сценарий Bash для начальной установки обоев с их каталогом в качестве рабочего. Без стартового сценария нам пришлось бы ждать смены обоев на подходящие до начала следующего промежутка в расписании (от 30 минут до 2,5 часов).
В остальное время Cron в нужные моменты заменяет текущую картинку-ссылку подходящей для следующего промежутка времени. Моменты смены обоев взяты с официальной презентационной страницы macOS Mojave. Для этого достаточно поиграться с ползунком, поглядывая на часы MacBook'а.
5) Установите из crontab.txt управляющую таблицу Сron для своей учётной записи:
crontab -u $USER ~/.mojave_dynamic/crontab.txt
6) Создайте файл стартового сценария обоев:
touch $HOME/.mojave_dynamic/mojave_dynamic_init.sh
Скопируйте в него текст из-под спойлера и сохраните:
#!/bin/bash
# Получить текущее время в формате "ЧЧММ"
currentTime=$(date +%H%M)
# Расписание обоев
# Номера обоев:
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# Моменты времени смены обоев:
wallpaperTime=(0600 0630 0700 0730 0800 1030 1300 1530 1800 1830 1900 1930 2000 2230 0100 0330)
# Элементы массива моментов времени:
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# Выбор номера обоев для текущего промежутка времени
# Правило: С (>=) [времяНачала] по (<) [времяОкончания] показывать обои No
[ "$currentTime" -ge "${wallpaperTime[0]}" ] && [ "$currentTime" -lt "${wallpaperTime[1]}" ] && wallpaperNumber=1
[ "$currentTime" -ge "${wallpaperTime[1]}" ] && [ "$currentTime" -lt "${wallpaperTime[2]}" ] && wallpaperNumber=2
[ "$currentTime" -ge "${wallpaperTime[2]}" ] && [ "$currentTime" -lt "${wallpaperTime[3]}" ] && wallpaperNumber=3
[ "$currentTime" -ge "${wallpaperTime[3]}" ] && [ "$currentTime" -lt "${wallpaperTime[4]}" ] && wallpaperNumber=4
[ "$currentTime" -ge "${wallpaperTime[4]}" ] && [ "$currentTime" -lt "${wallpaperTime[5]}" ] && wallpaperNumber=5
[ "$currentTime" -ge "${wallpaperTime[5]}" ] && [ "$currentTime" -lt "${wallpaperTime[6]}" ] && wallpaperNumber=6
[ "$currentTime" -ge "${wallpaperTime[6]}" ] && [ "$currentTime" -lt "${wallpaperTime[7]}" ] && wallpaperNumber=7
[ "$currentTime" -ge "${wallpaperTime[7]}" ] && [ "$currentTime" -lt "${wallpaperTime[8]}" ] && wallpaperNumber=8
[ "$currentTime" -ge "${wallpaperTime[8]}" ] && [ "$currentTime" -lt "${wallpaperTime[9]}" ] && wallpaperNumber=9
[ "$currentTime" -ge "${wallpaperTime[9]}" ] && [ "$currentTime" -lt "${wallpaperTime[10]}" ] && wallpaperNumber=10
[ "$currentTime" -ge "${wallpaperTime[10]}" ] && [ "$currentTime" -lt "${wallpaperTime[11]}" ] && wallpaperNumber=11
[ "$currentTime" -ge "${wallpaperTime[11]}" ] && [ "$currentTime" -lt "${wallpaperTime[12]}" ] && wallpaperNumber=12
[ "$currentTime" -ge "${wallpaperTime[12]}" ] && [ "$currentTime" -lt "${wallpaperTime[13]}" ] && wallpaperNumber=13
[ "$currentTime" -ge "${wallpaperTime[13]}" ] || [ "$currentTime" -lt "${wallpaperTime[14]}" ] && wallpaperNumber=14 # || -- Смена дня
[ "$currentTime" -ge "${wallpaperTime[14]}" ] && [ "$currentTime" -lt "${wallpaperTime[15]}" ] && wallpaperNumber=15
[ "$currentTime" -ge "${wallpaperTime[15]}" ] && [ "$currentTime" -lt "${wallpaperTime[0]}" ] && wallpaperNumber=16 # 15-0 -- Закольцовывание времени
# Назначить выбранные обои
rm $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg #удалить символическую ссылку на текущие обои
# источник ссылки назначение ссылки
ln -s $HOME/.mojave_dynamic/mojave_dynamic_$wallpaperNumber.jpeg $HOME/.mojave_dynamic/mojave_dynamic_x.jpeg #создать символическую ссылку на новые обои
# Убрать использованные переменные
unset currentTime
unset wallpaperNumber
unset wallpaperTime
exit 0
Сначала сценарий получает текущее время в удобном для дальнейшей обработки формате. Расписание смены обоев разворачивается в массив. Далее сценарий определяет среди всех промежутков времени текущий, сравнивая текущее время с их границами. Файл обоев заменяется ссылкой на картинку обоев, которая по номеру соответствует текущему промежутку времени. В конце работы стартовый сценарий "прибирается" за собой.
В блоке выбора времени две строки отличаются от других для обеспечения совместимости с предоставленным пакетом обоев и реальным течением времени.
7) Назначьте файл mojave_dynamic_x.jpeg фоновым изображением рабочего стола обычным для вашего DE способом. Например, для XFCE4 это ПКМ -> Сделать фоновым изображением. Динамические обои установлены и запущены.
Результат
В ходе испытаний на слабом Atom'ном нетбуке обои сменялись с задержкой в 4 секунды.
В целом, представленный способ может быть адаптирован для любого другого набора обоев и расписания их переключения. Расписание смены динамических обоев можно настраивать, согласованно редактируя и таблицу Cron (через crontab -e
), и файл стартового сценария mojave_dynamic_init.sh.
О своих действиях crontab отчитывается в syslog, а значит проверить "самочувствие" наших динамических обоев можно так:
cat /var/log/syslog | grep crontab | tail
Удаление
1) Восстановите исходную таблицу Cron:
crontab -r
2) Поменяйте обои на новые
3) Удалите папку динамических обоев:
rm -rf $HOME/.mojave_dynamic
Заключение
Работоспособность описанного метода успешно испытана на Debian 10 и Ubuntu 18.04 в окружениях XFCE4, GNOME3 и KDE5. Буду признателен если кто-нибудь подтвердит это для других дистрибутивов и DE. Метод может заработать и на BSD, так как его работоспособность зависит от используемого WM и поддержки символических ссылок файловой системой.