IT мемы с которыми я столкнулся

Этот пост буду старатся дополнять различными мемами с которыми возможно вы тоже столкнулись гуглив какой то термин или пытаясь исправить ошибку.

Бибайт мем

Во многих источниках часто говорят что в килобайте 1024 байт, и прочий бред. На самом деле в килобайте 1000 байт. Но в кибибайте 1024. Часто где эти понятия используются взаимозаменяемо, но на самом деле это абсолютно разные понятия.

В основном этот мем происходит в старой технической литературе, и в учебниках по информатике которые были написаны во времена Брежнева, и которые перепечатывались без проверки информации специалистами.

Мем с Systemd

Systemd это часть юникс систем которая позволяет настраивать запуск программ. Например если у вас есть программа-вебсервер то после перезагрузки машины вы хотите чтобы программа запустилась при старте, после инициализации системы. Каждая програма в Systemd представлена Unit-ом который можно настроить.

Мем состоит в том что у systemd unit есть 2 режима работы: simple, и forking. И многие люди неразбивающиеся как это работает ставят случайно эти режимы, взависимости от того какой шаблон юнита они нашли.

В итоге это приводит к тому что при неправильном выборе типа, systemd уходит в бесконечный перезапуск сервиса и последствия могут быть от неадекватной работы программы, до краша всей ОС.

Суть в том что forking ожидает от процесса самодемонизации и выхода. Ждет он этого примерно 5 минут, а потом убивает программу и рестартит её.

Если программа неподдержиает демонизацию, то следует использовать режим simple. Иначе systemd unit некогда не перейдёт в состояние успешной активации, и будет бесконечно пытатся рестартнуть программу.

Мем с сравнением [] в JS

Мне пришлось кучу времени потратить на дебагинг своего кода, чтобы понять что проблема была лишь в том что я сравнивал массивы javascript через ===. В JS сравнение массивов происходит не по их содержанию, а по айди объекта в памяти. Поэтому при сравнении любых двух массивов []===[] будет всегда false, независимо что находится внутри массивов. 

Тк я видел похожий код на php, то мне казалось что === проверит содержание массивов. Но оказалось что нет, в javascript эта логика не работает.

Поэтому перед сравнением арреек надо их превращать в неизменяемый тип, например string. JSON.stringify(a1)==JSON.stringify(a2).

Мем с конфликтом black с isort

Тк у нас был крупный проект, мы решили сделать все как полагается. Настроили кучу статических анализаторов кода, mypy, black, isort итд. В итоге почемуто когда я запускал black локально, то все проходило ок. А как загружал на наш CI/CD то всё валилось.

Причиной оказалось то что у нас сначала isort менял импорты, а потом black их менял под свой лад. В итоге и получилось что при запуске CI/CD они ломали друг друга из-за конфликтов. Оказалось что это не я один такой, и конфликт надо решать через конфиг profile = "black"

Мем с джанга не видит миграци если удалить папку миграций

На начальных этапах создания джанго веб приложений часто приходится менять модели/миграции тк часто нужно переносить их в разные части проекта. Поэтому, проще удалять папку миграций и БД целиком, вместо того чтобы каждый раз писать миграции. Тк данные реального приложения ещё не помещены, то так делать можно.
Но если удалить папку migrations/ с джанго проекта, то makemigrations перестаёт видить изменения моделей из этой папки.

Мем с clone3 + контейнеризацией

После того как я решил сбилдить свой образ приложения с тегом python:3 на старом докер сервере который я ставил ещё в 2021 году, мое приложение начало постоянно валится с ошибкой: RuntimeError: can't start new thread. 
 
Причина этой ошибки оказалось проста. Примерно с 2021 года большинство приложений используют clone3 вместо clone. clone это операция системного вызова для работы с потоками.
 
Проблема заключается в том что в всех контейнерных рантаймах стоят политики SECCOMP, в которых указываются белый список системных вызовов которые контейнер может совершить. И тк на тот момент clone3 несуществовало, то seccomp попросту блокирует системный вызов для спавна потока, из-за чего и возникает эта ошибка.
 
Чтобы воспрозвести проблему в современном докере можно просто заменить политику seccomp на кастомную, в которой заблокруем вызов clone3. 
ser@RDP31042770n:~$ cat deny-clone3.json
{
  "defaultAction": "SCMP_ACT_ALLOW",
  "archMap": [
    { "architecture": "SCMP_ARCH_X86_64", "subArchitectures": ["SCMP_ARCH_X86", "SCMP_ARCH_X32"] }
  ],
  "syscalls": [
    { "names": ["clone3"], "action": "SCMP_ACT_ERRNO" }
  ]
}
Затем запустим сам докер с этой политикой:
user@RDP31042770n:~$ docker run --rm   --security-opt seccomp=./deny-clone3.json   python:3.12-slim bash -lc 'python - <<PY
import threading
t = threading.Thread(target=lambda: None)
t.start(); t.join()
print("ok")
PY'
Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
  File "/usr/local/lib/python3.12/threading.py", line 994, in start
    _start_new_thread(self._bootstrap, ())
RuntimeError: can't start new thread
Проблема с Seccomp профилем сразу выдает ошибку спавна потока от питона.
 
Чтобы её исправить нужно: либо обновить seccomp профили на своем хосте докера, либо обновить сам докер (с ним поставляется новая политика seccomp, и таких казусов возможно небудет).
 
Либо залочится на древний докер образ в котором ещё не используют clone3 операцию. В моем случае я воспользовался последним вариантом, и просто залочился на хеш старого контейнера:
FROM python@sha256:3d3a5f478d2ba0e025e78e84c1dd468cff4d2f99a12d79d37a89294fc6d7ae41

ENV PYTHONUNBUFFERED=1

WORKDIR /code

COPY . /code/

RUN pip install -r requirements.txt

ENTRYPOINT ["python", "webhook.py"]
 

Мем с Tini

У нас возникла проблема, у нас стоял mediamtx в контейнере docker который спавнил дочерние процессы. У mediamtx стояла политика авторестартов, и из-за нестабильности сети многих клиентов у нас часто были вылеты этих процессов, и mediamtx в таком случае автоматически их спавнил обратно.
Но проблема была в том что накапливались зомби, со временем работы mediamtx и приходилось его регулярно перезапускать. Тк каждый zombie всеравно занимает собой pid, часто бывало что за пару дней работы попросту кончались pid для процессов, и всё замирало.

Решение

Дело в том, что когда ты респавнишь таким образом процесс в контейнере, то эти зомби некому чистить так-как большинство программ ожидают что зомбей будет убирать инит система, а не приложение само.

Когда мы запускаем любое приложение прямо на хосте например ubuntu, у нас стоит какая-то init система которая занимается такими низкоуровневыми вещами, например initd.
Но внутри контейнера такой системы нету, и внутренности контейнера находятся вне юрисдикции initd. Так что в итоге любая программа которую запустят как entrypoint контейнера, которая небудет обрабатывать зомби процессы, будет их плодить забивая себе пространство процессов.
Чтоб обработать зомби, необходимо просто сделать wait() на процессе чтоб он вышел из памяти. Но большинство приложений ожидают что это будет делать за них какой-то менеджер процессов который запущен выше них. В итоге и получается ситуация что зомби все забивают.

Решением стало то что я добавил в контейнер инит систему которая занимается как-раз wait всех процессов которые стали zombie. https://github.com/krallin/tini, после этого зомби перестали создаваться и пропадали как только появлялись.

Комментарии

Популярные сообщения из этого блога

DOS атака при помощи Python

Как установить charlesproxy и настроить ssl на google chrome

Взлом почты mail.ru live.com и yahoo.com