я тут себе очиститель папки upload замутил по хрону
скрипт cron_cleaner.pl.php:
Конечно ща первый вопрос "почему perl?"...
— Да по приколу :)
— В Перле есть шикарная возможность работы с хешами на собственной базе(снизит нагрузку на память)
— Он(perl) собстна разрабатывался для обработки текстов, а мы именно этим и будем заниматься сравнивая базы
второй вопрос "почему cron?"
— Да не желаю я раз в неделю лазить в админку и жмякать кнопку unfinder(искреннее спасибо Ris — вещь нужная)
всеравно не ведая чё тама удаляется
третий вопрос: "Чё за странное название скипт.php? када он на перле"
— Всё просто в папке upload запрещено правилами apache/nginx отдача php файлов, вот и шифруемся :)
ну и сам скрипт:
#!/usr/bin/perl -w $| = 1; ################################################################### # # Copyright (c) Fazer # cron_cleaner.pl # Version: 7.59 (2019-10-15) # Адаптированный под компонент "Очистка" # ################################################################### use strict; # Возможно потребуется доустановить пакеты use DBI; # yum install perl-DBI perl-DBD-MySQL perl-DB_File # or # apt-get install libdbi-perl libdbd-mysql-perl ####################################################################### # Конфигурация (множественные параметры - через пробел/запятую ) # # что бы реально удалять и переносить - поменять на: my $disabletest = 1; my $disabletest = 0; # my $disabletest = 1; # расширения файлов которые будут обрабатываться и удаляться при необходимости my $extension = "jpeg, jpg, gif, png, bmp"; # будет искать во всех ниже перечисленных полях всех таблиц в которых такие поля имеются my $fields = "photo photos image images img wm_image avatar content html cover_image logo picture"; # папки которые сканируем "внутри" ./upload/, например: "000/u1 004 images"; # если оставить пустым ($folders = "";), будет сканироваться вся ./upload/ исключая ./upload/deleted/ my $folders = "000"; # Список папок, исключенных из сканирования, ТОЛЬКО "ВЕРХНЕГО" уровня ./upload/NotDelete # например: "004, default" - не будет сканировать ./upload/004/ и ./upload/default/ my $exceptions = ""; # если установить в 'true' ненужные файлы будут удаляться безвозвратно а не переноситься в deleted my $delete = 'false'; # расположение папки конфигурационных файлов CMS относительно самого скрипта my $conf = '../system/config/'; ####################################################################### # Инициализация # $ENV{'PATH'} = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'; if (@ARGV){ if ($ARGV[0] && $ARGV[0] == 1){$disabletest = 1;} if ($ARGV[1]){$extension = $ARGV[1];} if ($ARGV[2]){$fields = $ARGV[2];} if ($#ARGV > 2){$folders = $ARGV[3];} if ($ARGV[4]){$exceptions = $ARGV[4];} } use DB_File; use File::Basename; use File::Find qw(finddepth); use File::Path qw(make_path); use Cwd; my (%db_connect, %result, @result, $str); my $prr = "No errors"; my $fullpath = dirname(__FILE__); my $dblock = tie %result, 'DB_File', "$fullpath/result.db", O_RDWR|O_CREAT, 0660, $DB_BTREE or die "Can't tie $fullpath/result.db: $!"; my $fd = $dblock->fd; open(FDB, "+<&=$fd") || die "Duplicate $!"; unless (flock (FDB, 2|4)) {print "Resource temporarily blocked by previous copy of the script\n";close(FDB);exit;} if ($disabletest){print "TestMode = 'OFF'\n";} else {print "TestMode = 'ON'\n";} my ($n, $h, $d, $m, $y) = (localtime)[1,2,3,4,5]; my $date = sprintf ("The start date is %04d.%02d.%02d %02d:%02d \n==================================\n", $y+1900, $m+1, $d, $h, $n); print $date; open (ERR, ">$fullpath/cleaner_errors.txt"); print (ERR $date); print (ERR "The script was running at those parameters:\n"); print (ERR "\$disabletest\t= $disabletest\n\$extension\t= $extension\n\$fields\t\t= $fields\n"); print (ERR "\$folders\t= $folders\n\$exceptions\t= $exceptions\n\$delete\t\t= $delete\n==================================\n"); if (open (LOGLINKS,"$fullpath/cleaner_select.txt")){ close (LOGLINKS); unlink ("$fullpath/cleaner_dirs.txt"); unlink ("$fullpath/cleaner_files.txt"); unlink ("$fullpath/cleaner_select.txt"); } chdir $fullpath or $prr='', print (ERR "Cant change $fullpath $!\n"); $fullpath = getcwd; # print "Am here $fullpath \n"; $folders =~ s/^(.\/|\/)//g; $folders =~ s/[\s|\r|\n|,]+/ /g; $extension =~ s/[\s|\r|\n|,]+/ /g; $fields =~ s/[\s|\r|\n|,]+/ /g; $exceptions =~ s/[\s|\r|\n|,]+/ /g; my @folders = split (/ /,$folders); unless (@folders){ my @exceptions = split (/ /,$exceptions); my $exceptions = 'deleted'; if (@exceptions){ foreach my $exc (@exceptions) { $exc=~s/\s//g; if ($exc){$exceptions .= "|".$exc;} } } # print "Exceptions - $exceptions\n"; opendir(DIR, "./") or $prr='', print (ERR "Cant open $fullpath $!\n"); my @dirs = grep { (!/^\./) && -d "./$_" } readdir(DIR); foreach my $dir (@dirs) { unless ($dir =~ m/^($exceptions)$/i){ push (@folders ,$dir); } } closedir (DIR); } # print "Folders - @folders\n"; my @extension = split (/ /,$extension); if (@extension){ $extension = shift (@extension); if (@extension){ foreach my $exp (@extension) { $exp=~s/\s//g; if ($exp){$extension .= "|".$exp;} } } } else { print (ERR " Nothing to do!,\n no valid extensions\n"); flock(FDB, 8); close FDB; unlink ("$fullpath/result.db"); print " Nothing to do!,\n no valid extensions\n"; exit; } # print "Extensions - $extension\n"; my @fields = split (/ /,$fields); if (@fields){ $fields = "'".shift (@fields)."'"; if (@fields){ foreach my $fi (@fields) { $fi=~s/\s//g; if ($fi){$fields .= ", '".$fi."'";} } } } else { print (ERR " Nothing to do!,\n no valid fields\n"); flock(FDB, 8); close FDB; unlink ("$fullpath/result.db"); print " Nothing to do!,\n no valid fields\n"; exit; } # print "Fields - $fields\n"; # print "ModeTest - $disabletest\n"; ####################################################################### # Обработка конфигурационных файлов # $conf =~ s/\/$//; open (CONF, "$conf/config.php") or (print (ERR "Can't open $conf at $fullpath: $!")), unlink ("$fullpath/result.db"), flock(FDB, 8), close FDB, print "Can't open $conf at $fullpath: $!", exit; while (<CONF>){ $str = $_; if ($str =~ m/.*'db_(.*)'.*=>.*'(.*)'/i){ $db_connect{$1} = $2; } } close (CONF); # while(($str,)=(each %db_connect)){ # print "$str = $db_connect{$str}\n"; # } # Обработка theme_*.yml файлов на наличие адресов картинок opendir(DIR, "$conf") or $prr='', (print ERR "Cant open dir $conf at $fullpath $!\n"); my @files = readdir DIR; closedir (DIR); foreach my $fileyml (@files) { if ($fileyml=~/.*\.yml$/i) { open (FILE, "$conf/$fileyml") or $prr='', print (ERR "Cant open $conf/$fileyml $!\n"); # print "$conf/$fileyml\n"; while (<FILE>){ $str = $_; my @str = split (/ |\r|\n/,$str); foreach $str (@str) { if ($str =~ m/(.*\/.*\.($extension)$)/i){ $result{$1} = undef; # print "$1 \n"; } } } close (FILE); } } ####################################################################### # Запрос к базе, поиск всех нужных полей # my $db = DBI->connect("DBI:mysql:$db_connect{'base'}:$db_connect{'host'}", "$db_connect{'user'}", "$db_connect{'pass'}", {mysql_auto_reconnect=>1}) or (print (ERR "Error connecting to database: $!")), unlink ("$fullpath/result.db"), flock(FDB, 8), close FDB, print "Error connecting to database: $!", exit; my $request = "SELECT DISTINCT TABLE_NAME,COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME IN ($fields) AND TABLE_SCHEMA='$db_connect{'base'}';"; my $answer = $db->prepare($request); $answer->execute; while (my @row = $answer->fetchrow_array) { push @result, [ $row[0], $row[1] ]; } $answer->finish; ############################################################### # Запрос к базе, создание хеша всех ссылок на изображения и файлы # open (LOGLINKS, ">$fullpath/cleaner_select.txt"); print (LOGLINKS $date); foreach my $tabfil (@result) { $request = "SELECT @$tabfil[1] FROM @$tabfil[0];"; # print "$request \n"; print (LOGLINKS "$request \n"); $answer = $db->prepare($request); $answer->execute; while (my @row = $answer->fetchrow_array) { # print "@row \n"; foreach my $src (@row) { if ($src){ my @src = split (/ |\r|\n/,$src); foreach $src (@src) { if ($src =~ m/src=\"\/upload\/(.*)\"/i){ $result{$1} = undef; # print "$1 \n"; } else { if ($src =~ m/(.*\/.*\.($extension)$)/i){ $result{$1} = undef; # print "$1 \n"; } } } } } } $answer->finish; } $db->disconnect; ############################################################### # Рекурсивный проход по upload, сравнение с хешем ссылок, удаление(в т.ч. пустых папок) # open (LOGDIR, ">$fullpath/cleaner_dirs.txt"); print (LOGDIR $date); open (LOGFILE, ">$fullpath/cleaner_files.txt"); print (LOGFILE $date); my $ifiles = 0; my $idirs = 0; foreach my $folder (@folders) { unless (opendir(DIR, $folder)){ print (ERR "Cant open ./upload/$folder/\n"); $prr=''; next;} closedir (DIR); finddepth \&recur, $folder; sub recur { if (-d) { # print " dir $fullpath/$File::Find::name\n"; opendir(DIR, "$fullpath/$File::Find::name") or $prr='', print (ERR "Cant open $File::Find::name: $!\n"); my $dir = (grep !/^\.\.?$/, readdir DIR); closedir (DIR); unless ($dir || (grep /^$File::Find::name$/, @folders)){ if ($disabletest){ rmdir ("$fullpath/$File::Find::name") or $prr='', print (ERR "cannot rmdir $fullpath/$File::Find::name: $!\n"); } $idirs++; # print "$File::Find::name \n"; print (LOGDIR "$fullpath/$File::Find::name\n"); } } else { my $fil = $_; if ($fil =~ m/.*\.($extension)$/i){ # print "file $fil\n"; unless (exists $result{"$File::Find::name"}){ # print " rm -> $File::Find::name\n"; if ($disabletest){ if ($delete =~ /^true$/){
Насколько понимаю в отличии от чистильщика от Ris, должна быть меньше нагрузка на сервер.
очиститель папки upload замутил по хрону
Проблема в том, что некоторые компоненты загружают в своих настройках технические изображения в те же папи, что и изображения в постах.
Например компонент изображений. Ватермарк в нем грузится тоже в папку upload/000/
Логотипы в шаблонах, логотип в компоненте RSS, и т.д.
И все это сносится при чистке чистильщиком((
Так что чистка по крону далеко не всегда возможна.
Но в целом, если действительно снизит нагрузку…
++
ЗЫ:
Думал о том как сделать, что бы не сносило нужные изображения....
Нужно поле (в компоненте Ris) или у Вас в скрипт как то прописать, поле исключений в которое можно было бы вписывать пути изображений которые исключались из очистки.
Их обычно не очень много, смотреть по инструменту разработчиков где находится и прописывать путь в такое поле...
Тогда можно бы было добиться очистки по крону…
А что нам мешает внести в поиск по базе те поля где описаны эти компоненты ?
Например компонент изображений. Ватермарк в нем грузится тоже в папку upload/000/
Логотипы в шаблонах, логотип в компоненте RSS, и т.д.
т.е. скажите какие таблицы/поля проверять на наличие этих картинок
А что нам мешает внести в поиск по базе те поля где описаны эти компоненты ?
Дописал пост выше, как наверное это могло бы быть...
скажите какие таблицы/поля проверять на наличие этих картинок
Так нет их этих полей в БД (насколько знаю), может ошибаюсь и не нашел...
ЗЫ:
Хм… точно… поля должны быть, просто надо найти…
это одна папка или список папок?
поле исключений в которое можно было бы вписывать пути изображений которые исключались из очистки.
это дерево или можно тупо по имени/именам фильтровать?
А мошть нам разработчики подскажут есть ли такие поля в базе или как можно отфильтровать по именам не проверяемые папки?
Например для компонента изображений таблица _images_presets, а поле для ватермарков wm_image (можно смело добавить в скрипт, "где искать")...
Так что мой вопрос снимается)...
Надо мне лучше было искать..).
подождите, в каком формате они хранятся ?,
Так что мой вопрос снимается)...
мой скрипт ищет по тегу <img src=
оно там так?
ищет по тегу <img src=
Нет. Там без тега так :
original: 000/u1/1/b/69c0e671.png small: 000/u1/9/5/bolshoi-wm-image-small.png
Даже если всё и найдется в БД (а я например так и не нашел поле от компонента PWA там в админке две иконки грузится), на мой взгляд проще админу записать не проверяемые скриптом пути исключения (от удаления), чем лазить по таблицам...
ЗЫ: вобщем проблема такая есть, а уж как решить её…
Я предложил, но не знаю насколько реализуемо.
а вот папки фильтровать боюсь не получится если они(папки) формируются так же динамически как и все остальные
думаю вы ещё не полностью выложились, поисчите плз есчё,
original: 000/u1/1/b/69c0e671.png
small: 000/u1/9/5/bolshoi-wm-image-small.png
должны быть теги иначе как они рисунки кажут та :)))
если у вас есть phpmyadmin попробуйте в нем поискать по имени рисунка "69c0e671.png"
должны быть теги иначе как они рисунки кажут та :
В компонете написаны теги, а в них выводятся только пути из БД...
Я не программист...
Но тегов нет:
У меня на серваке так:yum install libdbi-perl libdbd-mysql-perl
ну или как у вас там на серваке
No package libdbi-perl available.
No package libdbd-mysql-perl available.
Error: Nothing to do
Я пока занят. Может кто еще что напишет…
У вас видимо как то так
No package libdbi-perl available.
No package libdbd-mysql-perl available.
yum install perl-DBI
yum install perl-DBD-MySQL
согласен, если он(скрипт) будет терять картинки это — гомно :)
кто то не может себе позволить компонент по этой причине...
я думаю можно придумать признак по которому искать эти картинки,
просто у меня таковых нет и надо как то их смоделировать
зы
думаю стоит просто тупо по расширению (jpg, gif, png) попробовать, должно прокатить :)