- PVSM.RU - https://www.pvsm.ru -

Обманываем время: о тестировании с «подставным» временем на Linux и Docker

При разработке очередного бота для группы в 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/