Есть файл с гигантским json'ом, который нужно просмотреть глазами? Но смотреть его одной строкой без форматирования больно и неудобно. Поможет Python:
На выходе в консоли будет красивый отформатированный json с отступами, который легко читать и искать нужное.
cat patches/patches.json | python3 -m json.toolНа выходе в консоли будет красивый отформатированный json с отступами, который легко читать и искать нужное.
Чтобы открыть какой-то файл и в реальном времени видеть, что в него пишут, можно использовать
Но что делать, если в лог пишут очень активно, а вам нужен какой-то конкретный запрос, который вы, например, сами только что отправили в рамках дебага/тестирования? Увидеть глазами невозможно, потому что стена текста движется постоянно с большой скоростью.
Можно использовать grep. Но если использовать просто
-- то вы свой запрос не увидите, даже если отправите. grep буферизует результаты и будет ждать, когда появятся ещё какие-то строки, которые можно вывести. Чтобы grep выплевывал каждую новую одинокую появляющуюся строку, используйте опцию
Помните, что если используете цепочку грепов, то эту опцию нужно проставить каждому:
tail с опцией -f: $ tail -f /var/log/nginx/access.log
Но что делать, если в лог пишут очень активно, а вам нужен какой-то конкретный запрос, который вы, например, сами только что отправили в рамках дебага/тестирования? Увидеть глазами невозможно, потому что стена текста движется постоянно с большой скоростью.
Можно использовать grep. Но если использовать просто
grep вот так: $ tail -f /var/log/nginx/access.log | grep public.list
-- то вы свой запрос не увидите, даже если отправите. grep буферизует результаты и будет ждать, когда появятся ещё какие-то строки, которые можно вывести. Чтобы grep выплевывал каждую новую одинокую появляющуюся строку, используйте опцию
--line-buffered: $ tail -f /var/log/nginx/access.log | grep public.list --line-buffered
Помните, что если используете цепочку грепов, то эту опцию нужно проставить каждому:
$ tail -f /var/log/nginx/access.log | grep public.list --line-buffered | grep username --line-buffered
Ещё я недавно насмотрелась на то, как работают с linux другие и хочу спросить: вы же знаете про команду
Все команды, которые вы выполняете в терминале, сохраняются. Чтобы посмотреть историю, введите
Как быстро навигироваться по истории?
Варианты, как найти команду в терминале, которую вы вводили ранее:
1) если вы вводили ее только что или пару команд назад, то можно просто нажимать клавишу стрелки вверх -- вам последовательно будут показываться команды, которые запускались, от самой свежей к более старым,
2)
3)
Пользуйтесь
ctrl-r? Все команды, которые вы выполняете в терминале, сохраняются. Чтобы посмотреть историю, введите
history. Как быстро навигироваться по истории?
Варианты, как найти команду в терминале, которую вы вводили ранее:
1) если вы вводили ее только что или пару команд назад, то можно просто нажимать клавишу стрелки вверх -- вам последовательно будут показываться команды, которые запускались, от самой свежей к более старым,
2)
history | grep <команда> , выделить нужную команду, вставить, запустить -- это как раз тот способ, на который я насмотрелась и который сподвиг меня написать этот пост (не надо так), 3)
ctrl-r -- нажимаете сочетание этой клавиши и начинаете вводить команду, которая вам нужна, например ssh, вам покажут самую свежую команду, которая содержит эти символы. Если это не та команда (вы хотите подключиться к другой машине, к которой обращались раньше), то просто нажимаете ctrl-r ещё раз и ещё раз, пока не найдете нужное. Если нажать стрелку вправо, то команда вставится в терминал, но не выполнится (вы можете её редактивровать), если энтер -- команда сразу выполнится. Пользуйтесь
ctrl-r, это удобно!У вас есть сервер. А на сервере какой-то дикий треш с симлинками. Все друг на друга ссылаются. Симлинк на симлинк на симлинк. Как понять, что вот эта директория -- это то же самое, что вот эта директория? Могу ли я быть уверена, что вот тут:
Простой и быстрый способ:
Если числа, выплюнутые
/usr/share/kcare-eportal/patches/test/release лежит то же самое, что и вот тут: /var/www/html/test/release? Простой и быстрый способ:
[igrechikhina@patches ~]$ ls -d -i /usr/share/kcare-eportal/patches/test/release
1966244 /usr/share/kcare-eportal/patches/test/release
[igrechikhina@patches ~]$ ls -d -i /var/www/html/test/release
1966244 /var/www/html/test/release
-d, чтобы не показывать содержимое директории, а только её саму.-i, чтобы показать волшебное число для директории.Если числа, выплюнутые
-i, совпали для двух директорий, значит, это одна и та же директория (и вам нужно разбираться, кто кому симлинк).Продолжая тему "ты ли это" или как сравнить две сущности и убедиться, что это одно и то же. Иногда надо сравнить два файла на одной машине, иногда надо убедиться, что файл у себя на машине и где-то на удалённом сервере -- это один и тот же файл. Так вот --
Вот хочу узнать, одна ли и та же версия файла у меня в репе и сейчас на сервере:
На удалённом:
На своём:
Вижу, что нет, разные. Первое число -- чексумма, второе число -- размер, оба отличаются.
Ещё есть
cksum в помощь.Вот хочу узнать, одна ли и та же версия файла у меня в репе и сейчас на сервере:
На удалённом:
[root@patches2 ~]# cksum /usr/local/bin/kcare-deploy-prod
1081165413 480 /usr/local/bin/kcare-deploy-prod
На своём:
~$ cksum /home/lauvenhelz/dev/cldlnx/kernelcare/dist-server-scripts/kcare-deploy-prod
3998718679 616 /home/lauvenhelz/dev/cldlnx/kernelcare/dist-server-scripts/kcare-deploy-prod
Вижу, что нет, разные. Первое число -- чексумма, второе число -- размер, оба отличаются.
Ещё есть
md5sum, раньше пользовалась ею, но у неё длиннее выводимая чексумма, что не очень удобно, и нет информации о размере файла: [root@patches2 ~]# md5sum /usr/local/bin/kcare-deploy-prod
a490ae81807608ee2eafe35932cade41 /usr/local/bin/kcare-deploy-prod
Хочу отдельно обратить ваше внимание, что это команды именно для быстрой проверки для себя. Быстро убедиться, что файлы одинаковые или отличаются. Не используйте их в серьёзных задачах -- это ненадёжно (в
cksum коллизии возникают легко, в md5sum не так легко, но тоже возникают). Если вам нужна серьёзная проверка и контроль файлов в рамках реализуемой задачи, используйте, например sha256sum.Когда вы запускаете какую-то команду в консоли, вы, очевидно, запускаете какой-то файл. Как узнать какой и где он лежит? Есть команда
Можно посмотреть путь и потом использовать его в
А можно сделать всё в одну строчку:
Во-вторых, конструкцию
which. Во-первых, удобно использовать, чтобы узнать, "кого запускаем-то". Например, когда вы впервые залезли на сервер и разбираетесь, как работают все эти самописные скрипты. Вы не можете сделать cat <команда>, вам нужен путь до файла. Можно посмотреть путь и потом использовать его в
cat: [root@patches2 ~]# which kcare-deploy-prod
/usr/local/bin/kcare-deploy-prod
А можно сделать всё в одну строчку:
[root@patches2 ~]# cat `which kcare-deploy-prod`
#!/bin/bash
<...тут содержимое файла...>
Во-вторых, конструкцию
<команда> `which <другая команда>` можно использовать во всех остальных случаях (: Например, для предыдущего примера с cksum: [root@patches2 ~]# cksum `which kcare-deploy-prod`
3998718679 616 /usr/local/bin/kcare-deploy-prod
Мне нужно скачать с одного сервера на другой 27 гигабайт. На первый сервер я захожу по ssh и там надо запустить rsync, чтобы вытащить файлы со второго. Сеть отвратительная, будет качаться всю ночь. ssh иногда отваливается. Как быть уверенной, что процесс не помрёт в середине ночи от broken pipe'а, когда ssh отвалится? Ну, и лаптоп не хочется всю ночь включённым держать.
Используете
Теперь эта сессия будет живой до тех пор, пока вы не закроете её самостоятельно. Запущенная в ней команда в безопасности, не будет прервана и успешно отработает.
Чтобы зайти обратно, используйте
Можно создать несколько терминалов. Каждый раз запуская
Вводите нужный pid, например,
Чтобы убить ненужную больше эмуляцию, заходите внутрь и нажимаете
Используете
screen. Запускаете, он эмулирует терминал. Выполняете там необходимое (я запускаю rsync, например). И покидаете эмуляцию с помощью ctrl+a, затем d. Эта команда не окончит сессию, а просто позволит вам выйти, "отцепиться":[root@192-168-246-68 ~]# screen
[detached from 12233.pts-0.192-168-246-68]
Теперь эта сессия будет живой до тех пор, пока вы не закроете её самостоятельно. Запущенная в ней команда в безопасности, не будет прервана и успешно отработает.
Чтобы зайти обратно, используйте
screen -r. Можно создать несколько терминалов. Каждый раз запуская
screen, создается новая сессия. Когда захотите вернуться в конкретную сессию, нужно будет ввести её pid. Вот я ввожу screen -r, когда у меня есть несколько эмуляций и вижу: [root@192-168-246-68 ~]# screen -r
There are several suitable screens on:
16373.pts-0.192-168-246-68 (Detached)
12233.pts-0.192-168-246-68 (Detached)
Type "screen [-d] -r [pid.]tty.host" to resume one of them.
Вводите нужный pid, например,
screen -r 12233.pts-0.192-168-246-68 заходите. Чтобы убить ненужную больше эмуляцию, заходите внутрь и нажимаете
ctrl+d, на выходе вам сообщат об окончании сессии: [root@192-168-246-68 ~]# screen -r 16373.pts-0.192-168-246-68
[screen is terminating]
screen можно использовать не только на удаленных машинах, чтобы защититься от сломанного ssh, но и локально: чтобы, например, случайно не закрыть окно терминала, где выполняется какая-то долгая операция.И-и-и-и снова моя любимая рубрика про сравнение и нахождение отличий. Есть чудесный инструмент
Использовать в виде
1) строки уникальные для 1-го файла,
2) строки уникальные для 2-го файла,
3) строки, появляющиеся в обоих файлах.
И есть три опции:
Сейчас мне нужно понять, как отличаются файлы на двух серверах.
Сначала я сделала листинг интересующих меня директорий на двух интересующих меня машинах и сохранила их в соответствующие файлы:
(команда
Потом скопировала их к себе на машину и сравниваю:
Я хочу увидеть только те файлы, которые есть либо на одной, либо на другой машине, поэтому я использую опцию
Да, ещё напомню, что в конце вы можете легко посчитать количество отличающихся строк, добавив в строку
comm. Сранивает строки в отсортированных файлах. Использовать в виде
comm file-1 file-2. Умеет выводить три колонки: 1) строки уникальные для 1-го файла,
2) строки уникальные для 2-го файла,
3) строки, появляющиеся в обоих файлах.
И есть три опции:
-1 не выводить строки, уникальные для 1-го файла, -2 не выводить строки, уникальные для 2-го файла, -3 не выводить строки, которые есть в обоих файлах. Сейчас мне нужно понять, как отличаются файлы на двух серверах.
Сначала я сделала листинг интересующих меня директорий на двух интересующих меня машинах и сохранила их в соответствующие файлы:
[igrechikhina@patches ~]$ ls /var/www/html/ | cat > /tmp/prod.txt
[root@patches02 ~]# ls /var/www/html/ | cat > /tmp/stage.txt
(команда
cat здесь нужна, чтобы вывод ls был в виде одного столбца -- для comm это важно)Потом скопировала их к себе на машину и сравниваю:
comm -3 /tmp/prod.txt /tmp/stage.txt
Я хочу увидеть только те файлы, которые есть либо на одной, либо на другой машине, поэтому я использую опцию
-3, чтобы не видеть несколько тысяч пересекающихся между машинами файлов.Да, ещё напомню, что в конце вы можете легко посчитать количество отличающихся строк, добавив в строку
wc -l: comm -3 /tmp/prod.txt /tmp/stage.txt | wc -l
Испытываю некоторый стыд, потому что узнала полезное о штуке, которую вижу в мониторе ежедневно.
Все знают в лицо вывод
Это, если что, права:
Так вот. Перед правами есть еще символ
И с этим знанием я жила. Недавно мне попалась хорошая картинка, которая всё подтвердила и намеков на то, что мои знания не полны, не дала:
http://linuxcommand.org/images/file_permissions.png
Бывает символ
Но сегодня границы моего мира расширились. Я пошла погуглить, как определить, кто перед тобой -- симлинк или файл. И узнала невероятное: кроме
Офигеть. Я ведь (не) видела эту запись каждый день: у меня вся работа симлинками обмазана.
Но даже это не было пределом, потому что я погуглила ещё и прочитала вот эту статью, узнав что файлами, директориями и симлинками данные обозначения не ограничиваются: https://en.wikipedia.org/wiki/Unix_file_types
Все знают в лицо вывод
ls -la. Все знают, что в начале есть кусок с `rwx`'ами, который может выглядеть по-разному, например: -rw-------
-rw-r--r--
-rwxr-xr-x
-rwxrwxrwx
Это, если что, права:
read write execute для owner, group owner и всех остальных. Например, вот тут -rw------- owner имеет право читать и писать (`rw`), но не имеет права выполнять, а все остальные вообще никакими правами не обладают -- ничего не могут делать. А вот тут все подряд имеют права на всё (и читать, и писать, и выполнять): -rwxrwxrwx (для каждого прописано `rwx`). Так вот. Перед правами есть еще символ
-. И это не эстетики и форматирования ради, а пользы для. - в начале этой строки означает, что осматриваемая вами сущность -- обычный файл (regular file). И, кроме дефиса, я знала, что бывает еще d, например: drwxr-xr-x
drwxrwxr-x
d означает директорию. И с этим знанием я жила. Недавно мне попалась хорошая картинка, которая всё подтвердила и намеков на то, что мои знания не полны, не дала:
http://linuxcommand.org/images/file_permissions.png
Бывает символ
-, который означает файл, а бывает буква d, которая означает директорию. Всё. Но сегодня границы моего мира расширились. Я пошла погуглить, как определить, кто перед тобой -- симлинк или файл. И узнала невероятное: кроме
- и d есть ещё l. И l значит симлинк. И бывает вот так: lrwxrwxrwx
Офигеть. Я ведь (не) видела эту запись каждый день: у меня вся работа симлинками обмазана.
Но даже это не было пределом, потому что я погуглила ещё и прочитала вот эту статью, узнав что файлами, директориями и симлинками данные обозначения не ограничиваются: https://en.wikipedia.org/wiki/Unix_file_types
Сегодня про Python. Когда у меня возникает мысль хранить "много данных" в, скажем, словаре, а потом следом я думаю, что "ну, это же будет занимать много памяти, не надо так" -- я иду и проверяю, сколько конкретно памяти занимает это моё "много данных". Сначала считать и замерять -- потом делать какие-то выводы. Это очень облегчает жизнь, я уверена в результатах, у меня есть внятные аргументы в споре, я могу приводить конкретные значения вместо расплывчатых "это будет медленно", "мы упрёмся в память" и всё такое. Пока я готовлю большую статью про нагрузочное тестирование (выложу после новогодних праздников), вот подсказка, как быстро прикинуть, сколько места займет ваша будущая структура в памяти.
Мне нужно хранить 70 тысяч элементов в словаре, где в качестве ключа -- строка из 11-16 символов, а в качестве значения -- тьюпл вида (таймстемп, буль). Например,
Как проверить, сколько места он занимает?
Первым приходит на ум
Создаем список из 10к элементов:
Создаем словарь из 10к элементов, где в качестве значения ключа копия нашего ранее созданного списка (далее D_LIST), и такой же словарь из 10к элементов, но в качестве значения -- обычный инт (далее D_INT). Смотрим на размеры, которые вернет
Одинаковые. А ведь размер занимаемой памяти у D_LIST должен получиться где-то в районе 800М (размер самого списка в 87 килобайт умножить на 10к ключей).
Так как посмотреть, сколько памяти занято?
Есть модуль
Что видим? Данные для D_INT и D_LIST отличаются: 0.6М для D_INT (9952-9484) и 782М (793304 - 10576) для D_LIST. У D_LIST получились те самые "в районе 800М", которые мы обозначали выше -- можно верить.
И теперь осталось только посчитать память у нашего объекта, с которого началась вся затея:
Всего лиш
Мне нужно хранить 70 тысяч элементов в словаре, где в качестве ключа -- строка из 11-16 символов, а в качестве значения -- тьюпл вида (таймстемп, буль). Например,
{'JBcIMVrQYSJNEFxF': (1545814794, True)}. Сгенерировать такой словарь легко: >>> import time
>>> l = {str(i) + 'VrQYSJNEFxF': int(time.time()) for i in range(70000)}
Как проверить, сколько места он занимает?
Первым приходит на ум
sys.getsizeof(). В документации о нём написано: Return the size of an object in bytes. И это важно: sys.getsizeof() возвращает размер самого объекта, но не объектов, которые находятся внутри него. Почему это проблема? Смотрим: Создаем список из 10к элементов:
>>> l = [i for i in range(10000)]
>>> sys.getsizeof(l)
87624
Создаем словарь из 10к элементов, где в качестве значения ключа копия нашего ранее созданного списка (далее D_LIST), и такой же словарь из 10к элементов, но в качестве значения -- обычный инт (далее D_INT). Смотрим на размеры, которые вернет
sys.getsizeof(): >>> d_list = {i: l.copy() for i in range(10000)}
>>> sys.getsizeof(d)
295008
>>> d_int = {i: i for i in range(10000)}
>>> sys.getsizeof(d)
295008Одинаковые. А ведь размер занимаемой памяти у D_LIST должен получиться где-то в районе 800М (размер самого списка в 87 килобайт умножить на 10к ключей).
sys.getsizeof() возвращает размер самого объекта словаря на 10 тысяч ключей, а память, которую занимают объекты, лежащие в качестве значений, не учитывается. Нам не подходит.Так как посмотреть, сколько памяти занято?
Есть модуль
resource. Из документации: This module provides basic mechanisms for measuring and controlling system resources utilized by a program. Там же есть метод resource.getrusage(who), который возвращает объект, описывающий ресурсы, потребляемые текущим процессом. В качестве параметра можно передать три разные штуки. Каждая определяет, информацию о чем надо вернуть: для самого процесса, для его детей, для всех перечисленных. Нам нужно для самого процесса: resource.RUSAGE_SELF. В выхлопе будет с десяток разных элементов со своими показателями (всё описано в соответствующем разделе документации), нас интересует конкретный: ru_ixrss, показывающий shared memory size. То, что нужно, давайте пользоваться: >>> import time
>>> import resource
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
9484
>>> l = [i for i in range(10000)]
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
9952
>>> d_int = {i: i for i in range(10000)}
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
10576
>>> d_list = {i: l.copy() for i in range(10000)}
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
793304
>>> d_my = {str(i) + 'VrQYSJNEFxF': int(time.time()) for i in range(70000)}
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
803140
Что видим? Данные для D_INT и D_LIST отличаются: 0.6М для D_INT (9952-9484) и 782М (793304 - 10576) для D_LIST. У D_LIST получились те самые "в районе 800М", которые мы обозначали выше -- можно верить.
И теперь осталось только посчитать память у нашего объекта, с которого началась вся затея:
>>> import time
>>> import resource
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
9536
>>> d_my = {str(i) + 'VrQYSJNEFxF': int(time.time()) for i in range(70000)}
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
19360
>>> (19360 - 9536) / 1000
9.824
Всего лиш
ь 10 мегабайт на наш словарь с 70 тысячами ключей, в которых хранятся данные по времени + булевое значений. Мало? Мало. Наша стартовая мысль о "много данных, много памяти" была неверна.
Подводя итог:
1) всегда считаю и замеряю память-скорость-вотэвер перед тем, как заявлять, что что-то будет медленным-прожовливым-вставить-нужное,
2) замеры по памяти делаю с помощью
Подводя итог:
1) всегда считаю и замеряю память-скорость-вотэвер перед тем, как заявлять, что что-то будет медленным-прожовливым-вставить-нужное,
2) замеры по памяти делаю с помощью
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss.Клятвенно обещаю, что следующую большую статью сделаю отдельной ссылкой с форматированием и всем таким! Извините меня ещё раз, заметку писала на коленке, надеюсь, она полезна, несмотря ни на что (% Предыдущие большие заметки тоже переоформлю. Давайте вместе верить в меня, я справлюсь (%
Я снова хотела написать небольшую заметку, но вспомнила, что обещала начать пользоваться Телеграфом. Так вот, я смогла! Сегодня в очередной раз порадовалась тому, насколько легче стала моя жизнь с тех пор, как я полюбила awk, grep, sort, uniq и прочие маленькие (awk, это не про тебя) консольные утилиты -- и хочу поделиться случившимся кейсом. У меня есть файл, в котором содержится часть названий нужных мне файлов. Как быстро скачать их, не заморачиваясь с копированием путей и всем таким? Описала тут:
https://telegra.ph/Ne-delajte-rukami-to-chto-mozhno-sdelat-konsolnoj-komandoj-01-10
https://telegra.ph/Ne-delajte-rukami-to-chto-mozhno-sdelat-konsolnoj-komandoj-01-10
Telegraph
Не делайте руками то, что можно сделать консольной командой
Консоль -- это прекрасно. Вот у меня есть файл: ~$ cat /tmp/archives/public.list 11012018_2 1b0ca3a9834b0384ab32fe6dcb32de777 22022018_1 5914f4872e21ece2b0fe616b9a1317a62 10042018_3 386fb9c4a10e18ce7b96b9b6467ac5d66 13072018_1 76eb18b3116345a0f654985b7c6d93279…
Запускаете команду, у которой будет много выхлопа. И хотите, с одной стороны, в режиме реального времени видеть, что происходит, а с другой сохранить выхлоп в файл, чтобы проанализировать позже. Что делать? Использовать tee.
tee умеет перенаправлять свой input в два места: в stdout и в указанный вами файл.
Или сразу в несколько файлов (например, один вы хотите оставить в качестве референса, а второй планируете изменять):
python /tmp/convert.py | tee /tmp/convert.log
tee умеет перенаправлять свой input в два места: в stdout и в указанный вами файл.
Или сразу в несколько файлов (например, один вы хотите оставить в качестве референса, а второй планируете изменять):
# echo 1111 | tee /tmp/reference.txt /tmp/edit.txt
1111
# cat /tmp/reference.txt
1111
# cat /tmp/edit.txt
1111
Мне тут понадобилось удалить много-много маленьких файлов. Я знала, что удаляться они будут долго и мучительно. И хотелось видеть, что там на диске происходит -- как особождается память. Что я делаю? Использую
Как я уже сказала, мне хотелось видеть состояние диска. Для этого есть команда
watch. Эта штука будет запускать указанную ей команду каждые две секунды и в режиме фуллскрин будет показывать результаты её запуска. Как я уже сказала, мне хотелось видеть состояние диска. Для этого есть команда
df -- в её выхлопе можно увидеть значения used, available и процент свободного места на диске. Запускаю удаление файлов, в соседней вкладке запускаю watch df и в режиме реального времени вижу, как растет значение available и уменьшается значение used:То же самое можно делать и с параметризованными командами. Например, вы хотите видеть, как растёт файл, в который вы сейчас пишете. Используйте:
Чтобы выйти из фуллскрина watch'а -- ctrl+c.
watch ls -la /tmp/patches.json
Чтобы выйти из фуллскрина watch'а -- ctrl+c.
У меня есть таймстемп, например,
Использую
На всякий случай: таймстемп -- это seconds since the epoch, а epoch -- это 1970-01-01 UTC. Таймстемп всегда UTC.
Чтобы сконвертировать таймстемп в свое локальное время вместо UTC, убираю опцию
1549886527, и я хочу быстро сконвертировать его во что-то человекочитаемое. Использую
date: ~$ date -u -d @1549886527
Mon Feb 11 12:02:07 UTC 2019
На всякий случай: таймстемп -- это seconds since the epoch, а epoch -- это 1970-01-01 UTC. Таймстемп всегда UTC.
Чтобы сконвертировать таймстемп в свое локальное время вместо UTC, убираю опцию
-u:~$ date -d @1549886527
Mon Feb 11 15:02:07 MSK 2019
