- PVSM.RU - https://www.pvsm.ru -
При разработке очередного бота для группы в Telegram у меня возникла необходимость испытать его при различных значениях системного времени. Этот бот в конце каждого дня отправляет (или, в зависимости от ряда условий, не отправляет) сообщение в чат и производит манипуляции с некоторыми предыдущими своими сообщениями (или, опять же, не производит).
Менять системное время глобально ой, как не хотелось. Муторно, плюс у меня в ней столько всего понаставлено, не дай Б-г что-то заглючит (вряд ли, но мало ли). Думал запустить VirtualBox, но уж больно лень было ставить «чистую» Убунту, расшаривать папки, и т. д., тем более что этот вариант жрёт, как троглодит серьёзно потребляет машинные ресурсы.
Но буквально недавно я начал ковырять Docker. «У него просто обязан быть механизм контроля системного времени внутри контейнера», — подумал я. Рассмотрим, что же в результате вышло.
Итак, создаём контейнер и залезаем в него:
docker run -it ubuntu bash
Сразу скажу, что в контейнере я работаю как root
, поэтому sudo
не требуется.
Пробую:
date --set='2017-04-20 23:59:50'
Выдаёт date: cannot set date: Operation not permitted
Пробую:
hwclock --set --date='2017-04-20 23:59:50'
Выдаёт hwclock: Cannot access the Hardware Clock via any known method.
Не выходит. Немного погуглив, натыкаюсь на этот ответ [1]. Похоже, что Docker не настолько глубоко производит виртуализацию, как мне казалось. Он использует системное время, и тут уже никак не выкрутишься. Разве что можно поиграться с часовыми поясами, но в моём случае это не годится, мне нужен полный контроль над временем.
Ещё один вариант — в самой моей программе перехватывать вызовы к системному времени, но, опять же, муторно. Но буквально этажом выше есть ответ [2], указывающий на некую библиотеку libfaketime [3]. С помощью неё можно подставить «фальшивое время» для запускаемого процесса. Итак, устанавливаю её в контейнер:
git clone https://github.com/wolfcw/libfaketime.git
cd libfaketime
make install
Далее, следуя инструкции в ответе, запускаю бота с заданными переменными окружения:
LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1 FAKETIME_NO_CACHE=1 FAKETIME="2017-04-19 23:59:50" ./run.sh --debug#
Где в LD_PRELOAD
подставляем свежеустановленную библиотеку, а в FAKETIME
пишем время, которое хотим выставить для запускаемого процесса. FAKETIME_NO_CACHE
использовался в примере и предположительно отключает кеширование, используемое для повышения производительности. Не испытывал, но полагаю, что этот параметр необязателен.
Итак, программа запустилась, и действительно время выставилось так, как я хотел. Лишь с одной проблемой — время остановилось. Сообщения дебага показывают постоянно [2017-04-19 23:59:50]
. В этой библиотеке есть одна неинтуитивная особенность. Простое задание времени действительно задаёт и фиксирует его. Что бы время именно начиналось от данной точки, надо задать его, как FAKETIME='@2017-04-19 23:59:50'
. И врёмя пойдёт от этой точки.
Оказывается, всё даже проще. Чуть позже я обнаружил, что эта библиотека есть в стандартных репозиториях Ubuntu, и спокойно ставится через apt-get install faketime
. А запускается так:
faketime -f '@2017-04-20 23:59:50' ./run.sh
Не забываем про @ перед временем, здесь такой же синтаксис, но в довольно кратком man
это не сказано. Только в подробном описании [4] на Гитхабе.
Таким образом можно быстро и просто регулировать время, воспринимаемое запускаемой программой, будь она в контейнере Docker или в системе-хосте. В ответе [2] указывалось, что если нужно изменить «фальшивое время» из самой программы, то достаточно изменить глобальную переменную. К примеру, на Питоне:
os.environ["FAKETIME"] = "2020-01-01"
Возможно есть другие, более удобные способы регулирования времени для процесса? Расскажите о них в комментариях.
Автор: Highstaker
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/253038
Ссылки в тексте:
[1] этот ответ: http://stackoverflow.com/a/29561602/2052138
[2] этажом выше есть ответ: http://stackoverflow.com/a/41548434/2052138
[3] библиотеку libfaketime: https://github.com/wolfcw/libfaketime
[4] описании: https://github.com/wolfcw/libfaketime/blob/master/README
[5] Источник: https://habrahabr.ru/post/326772/
Нажмите здесь для печати.