10/06/2009: Панель ISPmanager: два штриха
1. Некорректная работа MySQL при исчерпании дисковой квоты.
При учете баз данных MySQL в дисковых квотах иногда возникает ситуация, когда при исчерпании квот
запросы на запись в MySQL блокируются, скапливается очередь из запросов и превышается лимит
max_connections.
Во избежание подобных ситуаций, можно использовать скрипт, который каждые несколько минут
проверяет квоты пользователей и, при приближении к лимиту, блокирует соответствующих пользователей
баз данных, оставляя им только права на чтение.
Скрипт quota.pl:
#!/usr/bin/perl use Mysql; $mysql_passwd="password"; $db = Mysql->connect("localhost","mysql", "root", $mysql_passwd); @quotas=`/usr/sbin/repquota -g /`; @users=`/bin/cat /etc/group | /bin/grep mgrsecure | /usr/bincut -d: -f4 | /usr/bin/awk 'BEGIN{RS=","}{print \$1}'`; foreach $user (@users) { $user=~s/\n//; $str=$user.'[[:space:]]*[-+]{2}[[:space:]]*([0-9]*)[[:space:]]*[0-9]*[[:space:]]*([0-9]*)'; foreach $line (@quotas) { if ($line =~ $str) { if (($2-2048) <= $1) { @bases=`/bin/ls -l /var/lib/mysql | /bin/grep " $user " | /usr/bin/awk '{print \$8}'`; foreach $base (@bases) { $db->selectdb('mysql'); $res = $db->query("select * from db where Db like '\%$user\%'"); while (@arr = $res->fetchrow) { $db->selectdb('use mysql_overquoters'); $res1 = $db->query("select count(*) from users where User='$arr[2]'"); @arr1 = $res1->fetchrow; if (!$arr1[0]) { $res2 = $db->query("insert into users values ('$arr[2]','$arr[3]', '$arr[4]', '$arr[5]', '$arr[6]', '$arr[7]', '$arr[8]', '$arr[9]', '$arr[10]', '$arr[11]', '$arr[12]', '$arr[13]', '$arr[14]', '$arr[15]', '$arr[16]', '$arr[17]', '$arr[18]', '$arr[19]',1)"); $db->selectdb('mysql'); $res2 = $db->query("update db set Select_priv='Y',Insert_priv='N', Update_priv='N',Delete_priv='Y',Create_priv='N',Drop_priv='Y',Grant_priv='N', References_priv='N',Index_priv='N',Alter_priv='N',Create_tmp_table_priv='N', Lock_tables_priv='N',Create_view_priv='N',Show_view_priv='N', Create_routine_priv='N',Alter_routine_priv='N',Execute_priv='N' where User='$arr[2]'"); } else { $res2 = $db->query("update users set overquoter=1 where User='$arr[2]'"); } } } } elsif (($2-3072) > $1) { $db->selectdb('use mysql_overquoters'); $res1 = $db->query("update users set overquoter=0 where user like \"$user%\""); } } } } $db->selectdb('use mysql_overquoters'); $res = $db->query("select * from users where overquoter=0"); while (@arr = $res->fetchrow) { @name=split (/_/,$arr[0]); push (@names,$name[0]); @list1=grep($_ eq $name[0],@names); $db->selectdb('mysql'); $res2 = $db->query("update db set Select_priv='$arr[1]',Insert_priv='$arr[2]', Update_priv='$arr[3]',Delete_priv='$arr[4]',Create_priv='$arr[5]', Drop_priv='$arr[6]',Grant_priv='$arr[7]',References_priv='$arr[8]', Index_priv='$arr[9]',Alter_priv='$arr[10]',Create_tmp_table_priv='$arr[11]', Lock_tables_priv='$arr[12]',Create_view_priv='$arr[13]',Show_view_priv='$arr[14]', Create_routine_priv='$arr[15]',Alter_routine_priv='$arr[16]', Execute_priv='$arr[17]' where User='$arr[0]'"); } $db->selectdb('use mysql_overquoters'); $res = $db->query("delete from users where overquoter=0"); $res = $db->query("flush privileges");
Скрипт написан для использования на серверах, на которых установлена панель управления ISPManager.
В скрипте предполагается, что директория с базами данных расположена в /var/lib/mysql и директория
/var не является отдельным разделом. При необходимости, пути в скрипте нужно изменить на правильные,
используемые на сервере.
Для работы скрипта необходимо создать базу данных mysql_overquoters с таблицей users со следующей структурой:
CREATE TABLE `users` ( `User` char(16) NOT NULL, `Select_priv` enum('N','Y') NOT NULL default 'N', `Insert_priv` enum('N','Y') NOT NULL default 'N', `Update_priv` enum('N','Y') NOT NULL default 'N', `Delete_priv` enum('N','Y') NOT NULL default 'N', `Create_priv` enum('N','Y') NOT NULL default 'N', `Drop_priv` enum('N','Y') NOT NULL default 'N', `Grant_priv` enum('N','Y') NOT NULL default 'N', `References_priv` enum('N','Y') NOT NULL default 'N', `Index_priv` enum('N','Y') NOT NULL default 'N', `Alter_priv` enum('N','Y') NOT NULL default 'N', `Create_tmp_table_priv` enum('N','Y') NOT NULL default 'N', `Lock_tables_priv` enum('N','Y') NOT NULL default 'N', `Create_view_priv` enum('N','Y') NOT NULL default 'N', `Show_view_priv` enum('N','Y') NOT NULL default 'N', `Create_routine_priv` enum('N','Y') NOT NULL default 'N', `Alter_routine_priv` enum('N','Y') NOT NULL default 'N', `Execute_priv` enum('N','Y') NOT NULL default 'N', `overquoter` tinyint(1) NOT NULL ) ENGINE=MyISAM;
Скрипт запускается по cron-у каждые 3—5 минут. Если у какого-либо пользователя останется 2 Мб
или меньше свободного места, у всех его mysql-пользователей будет заблокирована возможность
писать в базу данных. При восстановлении дисковой квоты, права на запись будут возвращены.
2. Очистка директорий с временными файлами пользователей.
Панель управления ISPManager создает такую конфигурацию, при которой у каждого пользователя есть
своя собственная директория tmp, в которой сохраняются сессии PHP. Операционная система не
следит за очисткой этих директорий, в результате чего, с течением времени в директориях
может скопиться очень много файлов. Это, в свою очередь, приведет к проблемам, например,
при резервном копировании.
Для периодической очистки директорий достаточно создать простое задание cron:
9,39 * * * * root find /var -wholename "*/data/tmp/*" -type f -cmin +120 -print0 | xargs -r -0 rm
В результате каждые полчаса будут удаляться временные файлы из директорий всех пользователей
в панели управления, к которым не обращались последние 120 минут.
https://www.io-hosts.ru/dikw/100609.php
Просмотров: 1498