Archive for the ‘Linux’ Category

Автозапуск скриптов

Появилась одна проблемка — после обновления сервера скрипты, которые раньше работали уверенно, начали вдруг умирать без видимых причин, выдавая напоследок содержательную фразу Killed.

После проверки все установок php, расхода памяти и т.п. проблема была обозначена как «а я хз почему» и были начаты поиски костыля.

И вот такой вот простой костылик, который поможет держать скрипт запущенным, даже если выставлены лимиты на память и время исполнения.

while [ 1 ]
   do php /path/to/script.php
done;

Просто и понятно. Единственный минус — скрипт сам по себе уже не остановится ))

Проверка доступности путей на файловых системах UNIX

Давненько ничего не писал в свой бложек. Вроде работы много, а все какая-то однообразная рутинная фигня, даже и стыдно писать про нее. Ну да ладно.

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

Итак, решил поначалу его на локале писать, потому как идея простая как две копейки и потребности кодить ее на боевом сервере нету.

Врубаю дезмитол, создаю папочку в дефолтной апачевской дире /var/www, готовлюсь к процессу. И думаю, а нафигаж я буду на локальном диске хранить проект, когда можно сделать симлинку в папку дропбокса. Делаю я симлинку, пробую открыть по пути localhost/folder и получаю 403. Это меня не расстраивает, поскоку апач не всегда по умолчанию открывает симлинки, ведущие на локальную файловую систему.

Правлю конфиги самого апача и дефолтного сайта, перезапускаюсь, заново открываю страницу и вновь получаю 403. Логи ничего вразумительного не говорят, я слегка огорчаюсь.  Проверяю права, группы, доступность папки, все верно. Но 403 не сдается.

После долгого курения гугла наткнулся на интересную утилитку под названием namei. Входит по умолчанию в бубунту. Проверяю доступность файла и получаю корень проблемы на блюдечке —

root@alex-desktop:/var/www# namei -m ./minutka/index.html 
f: ./minutka/index.html
 drwxr-xr-x .
 lrwxrwxrwx minutka -> /home/alex/Dropbox/minutka/
   drwxr-xr-x /
   drwxr-xr-x home
   drwxr-xr-x alex
   drwx------ Dropbox
   drwxrwxr-x minutka
 -rwxrwxrwx index.html

Вот такая вот полезная утилитка. Век живи — век учись, ага ))

Профилирование и отладка PHP скриптов

Отладка скриптов вообще дело крайне нужное и полезное. Кроме основной задачи — поиска и удаления ошибок, отладка прямо улучшает качество и работоспособность программы в целом. Выловленные баги, исправленная логика — все это делает программу стабильнее в работе, что весьма желанная цель при ее написании. Все ниженаписанное основывается на моем опыте, так что воспринимайте это как мое имхо ))

Read On…

Вложенные SQL запросы: одновременное добавление одинарных и множественных строк в INSERT

Понадобилось для одной задачи сделать выборку из таблицы А по определенным условиям и вставить ее в таблицу B.
Можно особо не заморачиваться, сделать SELECT  в переменную, потом пройтись циклом по INSERT и все.

Но это не очень красивое решение. Очень запросов много + на переменные память расходуется. Проще использовать вложенные запросы, они же nested queries. Но тут возникает проблемка —  если вставлять  только данные из INSERT, то все ок, но если добавлять еще и какие-нибудь неизменные значения, то выдается Subquery returned more than 1 value.

Чтобы не обьяснять на пальцах — сама таблица B

CREATE TEMPORARY TABLE `B` (
  `status` TINYINT(4) NULL DEFAULT NULL ,
  `pair` TEXT NULL DEFAULT NULL ,
)
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

Копируем из таблицы A и вставляем в B так

INSERT INTO `B` (`pair`) 
            SELECT `pair` FROM `A` ORDER BY RAND() LIMIT 100;

Если поле status имеет неизменное значение, например 123, то просто вот так уже не вставить

INSERT INTO `B` (`status`, `pair`) VALUES (
            (SELECT `pair` FROM `A` ORDER BY RAND() LIMIT 100),
            123);

Не совсем красивое решение нашел

UPDATE `B` SET `status` = '123' WHERE 1=1;

Но хотелось бы в одну строку все заделать. Отпишитесь плиз в коментах, кто знает, как реализовать.

Считаем, сколько строк кода в php проекте.

Упало в ридер несколько записей(раз, двас, трис), как посчитать строчки в си проектах и стало интересно, сколько же строчек я накропал для одного проекта. Оказалось, 5060, не считая js и css всяких.

Сама команда:

find . -type f -name "*.php" -exec wc -l {} +;

Скрипт для тюнинга MYSQL

Знакомый кинул линк на перловый скриптец, который собирает статистику из конфига и логов и выдает рекомендации по оптимизации бд.
Вот такой вывод:

-------- General Statistics --------------------------------------------------
[--] Skipped version check for MySQLTuner script
[OK] Currently running supported MySQL version 5.0.51a-24+lenny5-log
[!!] Switch to 64-bit OS - MySQL cannot currently use all of your RAM

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +Archive -BDB +Federated -InnoDB -ISAM -NDBCluster 

[--] Data in MyISAM tables: 5M (Tables: 260)
[OK] Total fragmented tables: 0

-------- Security Recommendations  -------------------------------------------
[OK] All database users have passwords assigned

-------- Performance Metrics -------------------------------------------------
[--] Up for: 1d 12h 14m 59s (4M q [33.837 qps], 39K conn, TX: 822M, RX: 460M)
[--] Reads / Writes: 30% / 70%
[--] Total buffers: 57.0M global + 50.5M per thread 
(400 max threads)
[!!] Allocating > 2GB RAM on 32-bit systems can cause system instability
[!!] Maximum possible memory usage: 19.8G (293% 
of installed RAM)
[!!] Slow queries: 10% 
(443K/4M)
[OK] Highest usage of available connections: 38% 
(152/400)
[OK] Key buffer size / total MyISAM indexes: 
15.0M/4.7M
[OK] Key buffer hit rate: 99.1% (9M cached 
/ 91K reads)
[OK] Query cache efficiency: 75.5% (2M cached / 
2M selects)
[OK] Query cache prunes per day: 0
[OK] Sorts requiring temporary tables: 0% (0 temp 
sorts / 439K sorts)
[OK] Temporary tables created on disk: 1% (8K 
on disk / 444K total)
[OK] Thread cache hit rate: 99% (307 created / 
39K connections)
[!!] Table cache hit rate: 0% (5 open / 
11K opened)
[OK] Open file limit used: 0% 
(11/65K)
[OK] Table locks acquired immediately: 99% 
(2M immediate / 2M 
locks)

-------- Recommendations -----------------------------------------------------
General recommendations:
    Increase table_cache gradually to avoid file descriptor limits
Variables to adjust:
  *** MySQL's maximum memory usage is dangerously high ***
  *** Add RAM before increasing MySQL buffer variables ***
    table_cache (> 32562)

Сам скрипт лежит тут: веб, гит

Простой способ проверки процесса на существование

Для простых многопоточных систем очень часто используют запуск в фоновом режиме.  Запускают их примерно вот так:

php script.php &

И управление процессом от юзера уходит, отловить такой процесс из другого скрипта уже не получится. А если процесс выполняет какую то одну и ту же задачу с интервалом по крону, и нужно, чтобы при запуска нового процесса старый был убит? Поймать его можно аццкой смесью bash + php:

$killPid = exec("ps ux | awk '/script_name.php/ && !/awk/ {print $2}'");//находим пид процесса
      if($killPid)//если есть, киляем
	  exec ("kill ".$killPid);
exec('php script_name.php &');//запускаем новый

Примеры использования strace для отладки скриптов

Strace — это встроенный перехватчик системных вызовов и сигналов в линуксе. Основная его цель — это перехват информации относительно какого-то процесса. Крайне незаменимая штука при отладке скриптов, особенно закодированных.

Пример использования — есть один сервис, который я написал, и обьявилась там проблема — каким-то неведомым образом права на файл, куда пишется лог, начали выставляться криво. А именно: вместо положенных rw — rw — rw стали w — wx — wT. Проблема тут в том, что надо указывать права при смене не как:

chmod('file.txt', '0666'); или
chmod('file.txt', 666);

в этом случае 0666 будет string, а вот так:

chmod('file.txt', intval('666', 8));

Так они уже будут в корректной форме.

Вернемся к проблеме. Нужно было найти, кто ставит на файл неверные права. Вот так можно отловить все вызовы определенного файла:

strace php ./script.php 2>&1 | grep file.txt

Ответ будет вида:

open("/path/to/file.txt", O_RDWR|O_CREAT|O_APPEND|O_LARGEFILE, 0666) = 4
chmod("/path/to/file.txt", 0666) = 0

Вот так можно отмониторить все обращения к файлу
Read On…

Что делать, если сбил все права?

Выставил я тут на рабочем сервере права на всю папку, в которой сайты лежат, 0777.  От души так, типа не жалко. Лучше и не спрашивайте, как так получилось))

Не, все работает конечно, но как-то немного стремно с полностью открытой на запись и выполнение папкой, доступной из веба жить 🙂 И папок вложенных куча, руками нереально все права поправить.

Вобщем, правится так.

Сначала всем ставим 0644

chmod -R 0644 ./*

Затем папкам ставим 0755

chmod -R 0755 ./$(find . -type d)

P.S. Ну и главное правило напоследок —  Не лезь, блять, с несоображающей головой на рабочий сервер. Надо сюда будет его отправить, там таких много))

P.P.S. Вики рулит )

Восстанавливаем текстовые файлы

find . -type f -exec chmod 644 {} \;

Потом папки

find . -type d -exec chmod 755 {} \;
css.php