Remote Shell через Telegram

Представляю простой Telegram Bot, позволяющий управлять сервером через Telegram.

Бот позволяет:

  • выполнять команды в интерпретаторе, например Bash;
  • загружать и скачивать файлы на сервер;
  • запрашивать пароль для доступа.

В репозитории доступен исполняемый файл под Linux а так же systemd unit файл.

https://github.com/pavelpatrin/teleshell

Подсчет статистики в консоли

Часто нужно посчитать в консоли статистику имея последовательность чисел, например, request_time из access-логов. Выгружать ее куда-то (в IPython, R и т.п.) можно, но это обычно слишком неудобно. Спешу поделиться инструментом, решающим проблему.

Встречайте, GNU DataMash: https://www.gnu.org/software/datamash/!
Уже есть в репозиториях Fedora, Ubuntu, etc. Нет зависимостей и всего 350кбайт!

Continue reading

Обновление Python в проекте на >500k строк

На этой неделе я завершил перевод Django-based проекта с Python 2.7 на Python 3.7. Это была наверное самая объемная и многоэтапная техническая задача за весь профессиональный опыт, поэтому выводы из этой задачи будет интересно сохранить на будущее.

Некоторые интересные цифры про процесс разработки.

  • Примерное количество Python-кода в проекте: >550k LOC.
  • Суммарное количество изменений в pullrequest-ах: >35k LOC.
  • Суммарное чистое время, понадобившееся на разработку: ~240h.
  • Количество потребовавшихся pullrequest-ов на код проекта: 13.
  • Количество задач на разработку, тестирование, раскладку: 17.
  • Покрытие кода тестами на момент начала разработки: >80%.
  • Суммарное чистое время, понадобившееся на тестирование: ~120h.
  • Количество найденных проблем ручным тестированием: 60.
  • Количество найденных проблем после релиза в продакшн: 8.

Некоторые интересные цифры про результаты.

  • Память на сервере больше не отъедается в python-аллокатор до конца. Теперь после нескольких часов работы объём памяти фиксируется примерно на одном уровне, и этот уровень в 2 раза меньше пиковых значений в старом варианте.
  • Время исполнения python-кода сократилось на 25%. Это видно как по тестовым сборкам (CI), так и в реальной нагрузке на продакшне.

Какие советы могу дать желающим провернуть что-то подобное.

  • Не бойтесь! Такая задача сложна только в смысле объема, но выполняя её по частям, плавно, поэтапно, её можно выполнить любой командой в любой ситуации.
  • Релизьте постепенно! Не допускайте единомоментных объемных и сложных изменений. Лучше выложить изменение за 10 PR-ов на 5к строк каждый и найти промежуточные проблемы, чем выложить разом 50к строк, которые разрабатывались в течение нескольких месяцев и собрать все проблемы разом.
  • Имейте тесты! Не стоит даже подходить к этой задаче, пока у вас нет тестов, или их покрытие небольшое. Например, в моей ситуации имея покрытие 80%, в ручные тесты проскочили >60 ошибок! Что бы было при покрытии в 50%, страшно представить.
  • Протестируйте руками! Автотесты необходимы, но они не гарантируют отсутствие ошибок. Перед финальным переключением интерпретатора сделайте полное ручное тестирование. Да, дорого. Но тестировать на пользователях – дороже.

Linux на современном десктопе

Выходные провел за обкаткой нового ПК под разными линуксами. ПК самый обычный: Intel 9600K, 16G ram, видео RTX 2070 и монитор 144Hz. Все завелось отлично, за исключением проблем с Nouveau (который вообще надо заблеклистить и исключить из поставки автоматически).

Список выводов которые я для себя сделал, перепробовав несколько вариантов:

  • Archlinux – я уже слишком стар для этого добра :(. Несколько лет назад с удовольствием ставил Arch и наслаждался отсутствием всего лишнего в своей сборке. Сейчас же хочется стабильной, надежной, поддерживаемой системы.
  • Fedora KDE – классная система и отлично подходит для дома. Серьезно, хоть какое-то ощущение “целостной, поддерживаемой системы”, заместо “набора странных временных решений”, пусть и пока на XServer, с этим смирился.
  • Wayland + Nvidia RTX – пока настроишь – пройдут все выходные. Проще временно отказаться от Wayland в пользу XServer (а точнее того, что другие уже сконфигурировали за тебя в дистрибутиве).
  • Nouveau + Nvidia RTX – это полная жесть, nouveau подтягивается автоматом даже в Live-режиме Арча и Федоры, и это ломает запуск системы (все виснет на запуске Journald). Чтобы запуститься хоть как-то приходится добавлять руками параметр nomodeset, блеклистить nouveau, и только потом настраивать систему.

Запускаем тесты параллельно и стабильно

Предположим, есть ситуация.

  • У вас есть проект с тестами, тесты идут долго и хочется их ускорить.
  • Вы распараллеливаете тесты на несколько рабочих процессов, они начинают работать быстрее, но периодически падают. А хуже того, единично запущенный упавший тест-кейс успешно проходит.

Что делать?

Continue reading

Выгружаем код из MacOS / Linux в облако

Часто не хочется запускать свой проект локально, т.к. батарейка садится, мак греет колени, жужжит и вообще тратит ресурсы. Куда удобнее запускать свой код в облаке.

Но как выгрузить свой код в облако?

Continue reading

Сравниваем структуры без учета порядка

Часто там нужно сравнивать одни части структур упорядоченно, а другие без учета порядке. Например, когда из API возвращается список с неупорядоченными значениями. Причем эти значения могут быть глубоко-глубоко внутри вложенного объекта.

class MyTestCase(unittest.TestCase):
    def test_one(self):
        data = make_request(...).json()
        self.assertEqual(data, {
            'root': {
                'sub': {
                    'items': ['a', 'b', 'c']
                }
            }
        })

Этот тест может падать, если на сервере структура items порождена, например, из set() или dict().values().
Что с этим делать? Предлагаю вот такое элегантное решение!

Continue reading

Пакетизируем PIP в RPM оперативно

Недавно в рамках задачи “сделать множество своих пакетов” с зависимостями проекта сделал вот такой вот скриптик.

Скриптик умеет упаковывать в RPM пакет указанный PIP пакет, корректно прописывать зависимости и добавлять префикс к имени.

Continue reading

Производительность собранного Питона

Сегодня пересобирал CPython 3.7 разными компиляторами под CentOS 7 в попытке приподнять его производительность.

Удивительно, но первая версия Python 3.7, собранная мной ранее со всеми оптимизациями, прогоняла наши тесты неприлично медленнее, чем Python 2.7 из поставки CentOS 7.

Python37, собранный мной с GCC 4.8.0 (CentOS bundled)
Параметры сборки: -march=x86_64 --enable-optimisations --with-lto
Ran 203 tests in 380.523s

Python27, входящий в стандартную поставку CentOS 7
Ran 203 tests in 288.164s

Вот что получилось из этого эксперимента.

Continue reading

Порядок элементов set-ов в Python

Проверьте себя, предположите, что выведет print?

list_1 = list(set([u'external_new', u'external', u'app_store']))
list_2 = list(set([u'app_store', u'external', u'external_new']))
print list_1 == list_2

А теперь проверьте себя еще раз

list_1 = list(set([u'external_new', u'external', u'app_store'] + range(100)))
list_2 = list(set([u'app_store', u'external', u'external_new'] + range(100)))
print list_1 == list_2

На самом деле, такое поведение очевидно, достаточно вспомнить, что внутри cPython set – хеш-таблица с открытой адресацией. Если количество элементов set-а приближается к количеству элементов внутреннего массива хеш-таблицы, вероятность коллизий повышается. В случае появления коллизий, преобразование set-а в список будет выдавать элементы коллизий в той последовательности, в которой эти элементы были добавлены в set.