Сегодня я вам расскажу, как современные web-разработчики должны правильно писать вот такую строчку:
<link rel="shortcut icon" href="/favicon.ico">
А давайте я расскажу вам про необычный баг в своем блоге, на борьбу с которым я потратил не один вечер.
Вс началось с того, что сайт перестал автоматически обновляться при добавлении поста или комментария. Вероятно, это произошло, когда я переехал на другой хостинг. Конечно же, первой мыслью было то, что перестал нормально отрабатывать WebHook на GitHub. Если кто не в курсе, WebHook — это запрос на определённый URL, который GitHub выполняет при коммите. Так вот, из настроек GitHub нужный URL никуда не исчез, да и изучение логов сервера показало, что запросы приходят нормально.
Запустил обновление ручками и увидел в конце консольного вывода строчку «Killed». Запустил на домашней машине — нет ошибок. Посмотрел потребление памяти и загруженность процессора. Показатели были в пределах нормы, да и полная перегенерация сайта (гораздо более долгая и затратная операция) отрабатывала как надо. Но я обнаружил, что swap-раздел отключён. Я его довольно быстро включил обратно, но проблема не исчезла. Swap не использовался, это и укоренило меня в мысли, что проблема не в ресурсах. А раз не в ресурсах, значит что-то не так с самой программой. Не буду рассказывать сколько вариантов компиляции я перепробовал, сколько исходников просмотрел. Ничего не помогало, более того, строка «Killed» нигде не встречалась. На некоторое время я отложил баг в сторону и запускал полную перегенерацию сайта по мере необходимости.
И уже потом я наткнулся на StackOverflow, что «Killed» может выдаваться ядром Linux в случае, если процессу пришёл сигнал SIGKILL (безапелляционное закрытие процесса). Но кто может отправлять этот сигнал моему процессу? Ну конечно, OOM (Out of Memory) Killer! Но ведь ресурсов достаточно, да и swap не используется, какой же тут Out of Memory? А ещё, судя по форумам, в системном логе (cat /var/log/kern.log
или dmesg
) при закрытии процесса OOM Killer’ом должна появляться строчка, что-то вроде:
ruby invoked oom-killer: gfp_mask=0x200da, order=0, oom_adj=0, oom_score_adj=0 ruby cpuset=/ mems_allowed=0 Pid: 27311, comm: ruby Not tainted 2.6.32-279.el6.x86_64 #1
У меня же были совсем другие записи.
Feb 4 02:28:44 dikmax kernel: [1430123.088968] select 1 (init), adj 0, size 146, to kill
Feb 4 02:28:44 dikmax kernel: [1430123.089000] select 378 (rsyslogd), adj 0, size 377, to kill
Feb 4 02:28:44 dikmax kernel: [1430123.089011] select 5584 (dropbox), adj 0, size 21725, to kill
Feb 4 02:28:44 dikmax kernel: [1430123.089018] select 17651 (dikmax-name), adj 0, size 86942, to kill
Feb 4 02:28:44 dikmax kernel: [1430123.089020] send sigkill to 17651 (dikmax-name), adj 0, size 86942
И всё, никаких деталей. Дальнейшие поиски навели на информацию о том, что похожие строчки могут встречаться на Android. И там их выдаёт lowmemorykiller — аналог OOM Killer. Ещё несколько запросов в гугл вывели причину их появления у меня: оказывается, lowmemorykiller был портирован в ядро Ubuntu (возможно, только серверную версию) и некоторое время там уже обитает.
Всё это хорошо, но ведь как показывают замеры, у моего приложения не было проблем с памятью и swap не использовался. Почему же тогда lowmemorykiller так нехорошо себя ведет? Ответ придет, если вспомнить, что Android — система с небольшим количеством памяти и совсем без swap-раздела. И lowmemorykiller ведёт себя соответственно платформе. Зачем ждать, пока память закончится, можно начинать убивать процессы заранее. Вот и у меня в соответствии с настройками первые кандидаты на убийство появлялись, если свободной памяти становилось меньше 64 Мб, а это целых 12.5% от памяти на сервере. Понятное дело, что до swap дело даже не доходило, что, конечно, не так плохо для общей производительности, но плохо для некоторых приложений.
Понимание проблемы позволило заняться поиском решения. Настойки lowmemorykiller можно поменять во время работы сервера с помощью записи в системные файлы /sys/module/lowmemorykiller/parameters
. Например, вот такая команда фактически выключает lowmemorykiller:
sudo echo '9999' > /sys/module/lowmemorykiller/parameters/adj && echo '1' > /sys/module/lowmemorykiller/parameters/minfree
Осталось только добавить команду в автозапуск. Как всегда crontab придёт на помощь. Только не забываем, что конкретно эта команда должна выполняться от имени root-пользователя и редактировать crontab нужно от его же имени (sudo crontab -e
).
@reboot echo '9999' > /sys/module/lowmemorykiller/parameters/adj && echo '1' > /sys/module/lowmemorykiller/parameters/minfree
По итогу 512 Мб оказалось недостаточно для нормального запуска обновления сайта. Но учитывая то, что оно выполняется всего несколько раз в неделю и не продолжается дольше 1-й минуты, использование 50 Мб swap мне не кажется большой проблемой.
Вот такая детективная история. Как обычно, комментарии горячо приветствуются и не оставляются без внимания.
Я уже год использую телефон под управлением Android, и за это время у меня сложились определенные пристрастия в отношении установленных программ. Решил поделиться этим списком, может, кто-нибудь откроет для себя что-то новое и полезное. Ваши комментарии и дополнения категорически приветствуются.
Camera ZOOM FX
Как-то купил на распродаже за $0.10. Лучше стандартной камеры тем, что можно нажать в любое место экрана, чтобы сфотографировать, а не только на кнопку в углу. Есть куча каких-то эффектов, которыми никто не пользуется. Ну и сетку можно нарисовать на экране, чтобы горизонт не заваливать.
exDialer
Замена стоковой звонилке. Быстро запускается, поддерживает T9-поиск по контактам. Особо хочу отметить возможность быстрого вызова контакта. Например, у тебя в списке на экране есть строчка с нужным контактом. Если сдвинуть ее вправо, то телефон начнет набирать этот номер, а если влево — откроет окно написания SMS. Таким образом, получаем одно касание экрана вместо нескольких.
GO Launcher EX
Рабочий стол. Стандартный от Google оказался слишком бедным на функции. А к тому времени, как поставил CyanogenMod с его ADW.Launcher, я уже слишком привык к GO Launcher.
GoldenDict
Словарь. Отличается от всех остальных поддержкой файлов ABBYY Lingvo. Там еще куча каких-то форматов, но я использую только этот, ну и hunspell для поиска с учетом словоформ.
Google Reader (умер)
Не думаю, что тут нужны комментарии.
GTasks
Список задач из Google. У меня на рабочем столе висит два виджета: со списком задач и со списком покупок. Хотя что-то я в последнее время перестал туда часто добавлять задачи, надо бы исправиться.
Moon+ Reader Pro
Хорошая, функциональная читалка. Можно даже прямо из нее скачать книгу с flibusta.net. Очень нравится анимация перелистывания страниц, похожая на настоящую книгу. Хотя многим она, вероятно, покажется лишней.
Opera Mobile
Функций стандартного браузера и Opera Mini оказалось маловато, поэтому использую это.
OsmAnd+
Карта. Она, конечно, не так шустро рендерится, как MapDroyd (более не доступен), но точно выигрывает по набору функций. Можно даже показывать точки из wikipedia и читать статьи, не подключаясь к интернету.
QuickPic
Как-то мне надоело, что стандартная галерея стартует полчаса и содержит кучу мусора из разных папок на карте памяти. Начал искать альтернативу. QuickPic позволяет показывать картинки начиная с определенной папки, да и стартует за секунду.
Smart AudioBook Player
Очень клевый плеер для аудио книг. Много мелких удобных функций вроде перемотать немного назад, когда нажимаешь воспроизведение.
Sports Tracker
GPS-трекер. Из всех опробованных трекеров этот лучший по интерфейсу. Простой, красивый, удобный. Ну и, конечно, автоматичекая синхронизация с сервером. Причем сохраняется не только трек, но и все фотографии, сделанные во время прогулки, с привязкой к карте.
SwiftKey 3 Keyboard
Клавиатура. Дополняет слова и исправляет опечатки. В новой версии она научилась вставлять пропущенные пробелы, теперь осталось только научиться удалять лишние. Старается предсказывать слова на основе предыдущих набранных, иногда это даже получается. И уж точно это лучшая клавиатура из всех, что я попробовал.
TransPot
Может кто еще ее не знает, но это программа отвечает за общественный транспорт Минска. Можно посмотреть, через сколько на остановку приедет нужный тебе троллейбус/автобус. Единственное, чего не хватает, — поиск маршрутов.