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
Просмотров: 1508