[spip-dev] cache énorme sous SPIP 2.0.1.0 - solution

Salut,

sur un site sous SPIP 2.0.1.0 que je n'ai pas suivi depuis quelques
mois je viens de me retrouver avec un cache de plus d'un GO. Le site
était devenu très lent et j'avais d'abord pensé que mon vieux serveur
était simplement trop lent, mais non ...

La solution consite simplement (je suppose, je vais la lancer demain)
dans une mise à jour verst SPIP 2.1 (s'il n'y a pas de question de
compatibilité avec des plugins ...) mais comment faire pour se
débarasser de ces tonnes de fichiers cache ?

Pas question de les effacer par FTP (il y a au minimum 16 dossiers
avec plusieurs dizaines de milliers de fichiers dans chacun) alors
j'appelle mon admin (manque de peau c'est moi-même) et il commence à
vouloir rm -r /htdocs/monsitespip/tmp/cache/*
Résultat : /bin/rm: Argument list too long
Impossible d'effacer cette myriade de fichiers.

Maintenant il y a deux solutions :

Effacer par groupe
rm -r /htdocs/monsitespip/tmp/cache/1/*
etc.
ca dure des heures parce qu'il faut précéder par dossier et par
sous-groupe de x fichiers ...

ou bien

´find . -name '*' -print0 | xargs -0 rm

Pourquoi ? C'est dû à une limitation du kernel Linux.

C'est très bien expliqué ici :
http://www.moundalexis.com/archives/000035.php

Est-ce que vous avez déjà rencontré ce problème? Comment avez-vout fait?
klaus++

vouloir rm -r /htdocs/monsitespip/tmp/cache/*
Résultat : /bin/rm: Argument list too long
Impossible d'effacer cette myriade de fichiers.

rm -rf tmp/cache/*/

mais on devrait peut-être passer à un cache plus fragmenté, en 256
sous-répertoires :

- $subdir = sous_repertoire($repertoire, substr($md_cache, 0, 1), true);
+ $subdir = sous_repertoire($repertoire, substr($md_cache, 0, 2), true);

(évidemment ce patch ne suffit pas, il faut aussi revoir le cron qui
nettoie les sous-répertoires)

-- Fil

J'ai déjà rencontré le problème sur des sites en 1.9.x, avec un cache qui explose à plus d'1Go, en effet.
J'avais du coup amélioré le process de vidage du cache pour qu'il passe en mode "vidage d'urgence" au dela d'un certain dépassement de limite.
De ce que j'ai compris, ce problème se pose essentiellement suite à une visite de robots fous qui génèrent des caches à tire l'arigot avec des paginations croisées, entre deux passage du cron de vidange.
Du coup, au passage suivant, le cron n'arrive même plus à compter la taille du cache ni à le vider, si le serveur est trop lent, et plus rien ne retient l'orgie de fichiers.

Je n'ai pas re-rencontré le soucis depuis que j'ai déployé l'écran de sécurité qui prémunit contre les visites de robots fous sur les paginations croisées, tu devrais le déployer.
Cédric

vouloir rm -r /htdocs/monsitespip/tmp/cache/*
Résultat : /bin/rm: Argument list too long
Impossible d'effacer cette myriade de fichiers.

rm -rf tmp/cache/*/

non, je confirme en effet que dans ce genre de situation, la vidange est bien pénible, j'avais fait un script sh pour ça, du coup ...

mais on devrait peut-être passer à un cache plus fragmenté, en 256
sous-répertoires :

- $subdir = sous_repertoire($repertoire, substr($md_cache, 0, 1), true);
+ $subdir = sous_repertoire($repertoire, substr($md_cache, 0, 2), true);

Oui, on pourrait, mais je ne sais pas si ça va être décisif.

Cédric

Merci, je croyais que l'écran de sécurité était seulement utile pour des sites sous SPIP avant 2.0 qu'on ne pouvait pas mettre à jour pour une raison ou une autre.

Je n'ai pas re-rencontré le soucis depuis que j'ai déployé l'écran de sécurité
qui prémunit contre les visites de robots fous sur les paginations croisées,
tu devrais le déployer.
Cédric

Malheureusement -f n'a rien changé au problème. Mais je n'ai pas utilisé la notation ./cache/*/ avec slash - j'utilisais ./cache/*

rm -rf tmp/cache/*/

non, je confirme en effet que dans ce genre de situation, la vidange est bien pénible,
j'avais fait un script sh pour ça, du coup ...

Faudra enfin que je m'y mette, pourtant j'étais le roi des *.BAT sous DOS :wink:

klaus++

J'ai déjà croisé ce genre de situation aussi. C'était avec un accès restreint pour le coup de mémoire, sur un site d'alexandra, que nous avons résolu avec :

Supprimer un énorme dossier lorsque rm indique qu’il y a trop de fichiers :

Se mettre dans le dossier puis (pour des fichiers dont les noms utilisent des caractères hexadecimaux) :

for i in `seq 0 9` a b c d e f; do for j in `seq 0 9` a b c d e f; do echo "Suppression de $i$j*"; rm $i$j*; done; done

Matthieu.

Merci encore. C'est pas facile la déstruction à grande échelle :wink:
klaus++

Matthieu Marcillaud wrote:

03/06/10, klaus++:

Pas question de les effacer par FTP (il y a au minimum 16 dossiers
avec plusieurs dizaines de milliers de fichiers dans chacun) alors
j'appelle mon admin (manque de peau c'est moi-même) et il commence à
vouloir rm -r /htdocs/monsitespip/tmp/cache/*

rm -r tmp/cache && mkdir tmp/cache && chmod $qui_va_bien tmp/cache

Jamais testé, mais ça devrait suffire non ?

Non, non, quand il y a trop de fichiers, on n'arrive plus à rm un répertoire, la commande echoue car il n'arrive pas à lister les fichiers contenus pour les supprimer.

Cédric

Justement non :

rm -r /htdocs/monsitespip/tmp/cache/*
Résultat : /bin/rm: Argument list too long

Pour le moment on a trois solutions :

J'ai effacé par groupe
rm -rf /htdocs/monsitespip/tmp/cache/1/*
etc.

On peut contourner le prblème avec des pipes :
´find . -name '*' -print0 | xargs -0 rm
Source: http://www.moundalexis.com/archives/000035.php

La solution de Matthieu:
Se mettre dans le dossier puis (pour des fichiers dont les noms utilisent des caractères hexadecimaux) une ligne de commande:
for i in `seq 0 9` a b c d e f; do for j in `seq 0 9` a b c d e f; do echo "Suppression de $i$j*"; rm $i$j*; done; done

Cédric indique que l'écran de sécurité empêche les robots de faire exploser le cache

Fil propse de modifier SPIP et de passer à un cache plus fragmenté, en 256 sous-répertoires.

klaus++

davux wrote:

03/06/10, klaus++:

Justement non :

rm -r /htdocs/monsitespip/tmp/cache/*
Résultat : /bin/rm: Argument list too long

Juste pour clarifier : ce n'est pas la même raison. Ça, c'est parce que
le shell développe le * en une longue liste, du coup rm reçoit des
milliers d'arguments, d'où ma proposition de "rm -r tmp/cache" tout
court (juste deux arguments du coup à l'appel du programme).
Mais effectivement Cédric semble dire que c'est même un problème
interne du noyau (donc pas juste une histoire de liste d'arguments trop
longue), pas juste de l'appel à rm.

L'histoire du noyau est expliquée dans cet article :
http://www.moundalexis.com/archives/000035.php

"the command line should look like this...

find . -name 'spam-*' -print0 | xargs -0 rm

and the explanation: in the linux kernel is the function execve(),
which is how all of the other exec() functions (execl, execlp, execle,
etc.) are actually implemented. the way it works is by creating a 128K
buffer at the top end of the memory space and copying the command line
and environment for the new process into this space. it then loads the
new program into memory, sets its argv and envp pointers, and jumps to
its entry point.

there's a lot more to it than that, but the point is that there is a
128K buffer which is the only thing "held" from the parent process to
the child. the "Argument list too long" error message is actually the
kernel's E2BIG error code, returned when the execve() is not able to
fit the supplied argument list and environment into the 128K buffer."

klaus++

davux wrote: