Cik ilgā laikā var izdzēst miljonu mapju?

Jun 08 2020

Lai arī studijas Latvijas Universitātē esmu beidzis jau vairākus gadus atpakaļ, no tām man "mantojumā" ir palicis serveris
ante.lv, kuru savulaik izmantojām dažādu atvērtā pirmkoda rīku (FTP failu apmaiņai, Subversion versiju kontrolei, tīmekļa servera ar XWiki u.c.) darbināšanai. Serveris praktiski bez izmaiņām ir darbojies kopš 2015. gada. Ja neskaita vispārīgu Sigmanet resursu pārraudzību un servera pārraudzību ar Munin, tas praktiski gadiem ir dzīvojis kā nepieskatīts bārenis (vai patstāvīgs pieaugušais, ja serveru gadus rēķina kā suņu gadus.)

Pirms pāris dienām no Munin saņēmu e-pastu, ka šim serverim ir bīstami piepildīts disks.

Att01.png

Katrs zina, ka diskā var ierakstīt tikai noteiktu daudzumu datu (parasti daudzus simtu GB vai dažus TB), bet bez tā diskā ir ierobežots arī maksimālais failu un mapju skaits. Ja operētājsistēma un failu sistēma ir sakarīga (t.i. 64-bitu operētājsistēma un EXT4 failu sistēma, kas ir Linux standarts1), tad šis skaits ir tik liels, ka pieejamais failu un mapju skaits parasti netiek izsmelts, jo failu datiem vietas pietrūkst ātrāk. Bet šim serverim diskā izlietotais datu apjoms bija normāls2:

df -h /
Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/ip101--vg-root   19G   10G    9G  53% /

Tam nez' kāpēc sāka trūkt failu un mapju rādītāja ierakstiem, jeb "inodēm" atvēlētā vieta:

df -i /
Filesystem                  Inodes   IUsed  IFree IUse% Mounted on
/dev/mapper/ip101--vg-root 1228800 1130618  98182   92% /

Kā redzams, no rezervētajām 1,2 miljoniem bija izlietoti ap 1,1 miljoni, brīviem paliekot "tikai" nepilniem 100 tūkstošiem ierakstu. Lai satura rādītāja "inodēm" sāktu trūkt vietas, failiem ir jābūt ļoti daudziem un ļoti maziem. Vispirms es turēju aizdomās uz servera ejošo Yacy vienraga meklēšanas dzinēju, bet tur vaina (it kā)3 nebija.

Lai arī visu žurnāla failu arhivēšana notiek automātiski, kaut kas tur var aizķerties, tāpēc izpildīju laika gaitā papildinātu skriptu, kura saturs ir sekojošs:

#!/bin/bash
echo 0
find /var/log/ -type f -name "*.[0-9]" -exec rm -f {} \;
echo 1
find /var -type f -name "*[0-9].gz" -exec rm -f {} \;
echo 2
find /var -type f -name "*log*[0-9]" -exec rm -f {} \;
echo 3
find /var -type f -name "*.old" -exec rm -f {} \;
echo 4
find /var/log -type f -mtime +365 -exec rm {} \;
echo 5
printf "logs were removed at:`date`\n">>/var/log/messages

Tas izdrukāja:

0
1

un tad praktiski apstājās. Sapratu, ka kaut kas nav labi ar failu meklēšanu var mapē. Ātrdarbības uzlabošanai, tīmekļa serviss uz šī servera iet ar kešošanu, kas glabā visus XWiki dinamiski un tāpēc lēnāk ģenerētos datus kā statiskus HTML failus. Lai arī keša attīrīšana darbojas automātiski, pieņēmu, ka kaut kas tajā ir salūzis. Izpildīju komandu:

htcacheclean -v -p /var/cache/apache2/mod_disk_cache/ -l1024M -L64k

Serveris pēc teju stundu ilgām pārdomām atgrieza:

Cleaned /var/cache/apache2/mod_cache_disk. Statistics:
size limit 1024.0M
inodes limit 65536
total size was 171.7M, total size now 1.0M
total inodes was 66095, total inodes now 64001
total entries was 1047, total entries now 85
963 entries deleted (0 from future, 221 expired, 741 fresh)

Tomēr, izmantoto inožu apjoms diskā praktiski nemainījās.

Pēc StackExchange padoma mēģināju sameklēt, kurā tieši vietā mapē ir šis nenormālais failu/mapju apjoms, bet nespēju sagaidīt skripta beigas. Uz cita servera skripts ar aptuveni 300 tūkstošiem failu (gan vienu, gan otru variantu) izpildījās aptuveni 2 minūtēs, bet uz ante.lv likās, ka es no garlaicības nomiršu ātrāk, nekā tas parādīs atbildi.

Beigās sapratu, ka jāstrādā vien pašam ar savu prātu (un rokām) un pakāpeniski pildīju šādas komandas:

for i in $(ls); do printf "$i\t"; find $i|wc -l; done

Sliktā/aizdomīgā mape bija tā, kuras nosaukums tika izdrukāts, bet apnika gaidīt meklējuma rezultātu. Tā pamazām atklāju, ka / mapē sliktā mape bija var, tajā — apache2, bet tajā — mod_disk_cache.

mod_disk_cache mapē Apache keša serviss glabā HTML failus, kuru atrašanās vietu nosaka faila satura jaucējsumma, pierakstīta Base-64 kodējumā. Katrā no mapes līmeņiem ir ap 100 mapēm, kurā atkal ir ap 100 mapēm, tad vēl un vēl ap 100 mapēm, kurās (ja ir) atrodas kešotie HTML faili:

├── mod_disk_cache
│   ├── _
│   │   ├── _
│   │   │   ├── 0r69dtmhG4JBsEFhfhuA.header.vary
│   │   │   │   └── y
│   │   │   │       └── f
│   │   │   │           ├── x3PIzh0_AR3cCkuV7fvA.data
│   │   │   │           └── x3PIzh0_AR3cCkuV7fvA.header
│   │   │   ├── 1ghMuUqbLb_ypS1WgQGg.header.vary
│   │   │   │   └── X
│   │   │   │       └── t
│   │   │   │           ├── 3rHvFOfDp5093_bmgYhQ.data
│   │   │   │           └── 3rHvFOfDp5093_bmgYhQ.header
...

Lai arī regulāri izsauktais htcacheclean process izdzēš vecos HTML failus, atklājās, ka tas neizdzēš tukšās mapes un pēc vairāku gadu servera darbības /var/cache/apache2/mod_disk_cache mapē bija pāri miljonam apakšmapju, vairums ko kurām bija tukšas. Rezultātā, diskā sāka trūkt vietas satura rādītāja "inodēm", bet pieejamais apjoms failu datiem pietika.

Kad sapratu vainu, risinājums bija vienkāršs.

Apturēju apache serveri:

service apache2 stop

Un liku izdzēst visu mapi:

rm -fr /var/cache/apache2/mod_disk_cache &

(Vispirms dzēšanas komandu palaidu kā interaktīvu procesu, bet tad sapratu, ka tas ies tik ilgi, ka ir jāatstāj kā fona process ar & komandas beigās, jāatstāj serveris strādājot un jāiet gulēt.)

Es pārvaldu vairākus serverus, kuros darbojas Apache tīmekļa serviss ar kešošanu, bet līdz šim nevienu serveri nebiju darbinājis tik ilgi, lai pamanītu, ka mapju skaits kešā tikai pieaug. Iespējams, ka serveri kāds ļaunprātis bija pārbaudījis uz izturību, jo Munin pārskatā redzam, ka izmantoto inožu apjoms straujāk ir pieaudzis pēdējo mēnešu laikā:

Att02.png

Nākamajā rītā apskatījos, ka mape ir izdzēsta un diska "satura rādītājs" ir atbrīvots:

df -i /dev/mapper/ip101--vg-root
Filesystem                  Inodes  IUsed   IFree IUse% Mounted on
/dev/mapper/ip101--vg-root 1228800 141094 1087706   12% /

Atjaunoju jaunu, tukšu keša servisa mapi, uzliku pieejas tiesības un palaidu Apache servisu:

mkdir /var/cache/apache2/mod_disk_cache
chown -R www-data:www-data /var/cache/apache2/mod_disk_cache
service apache2 start

No Munin pārraudzības grafika noteicu, ka 1087706 mapes ir izdzēstas divu stundu laikā, jeb aptuveni 150 mapes sekundē.

Att03.png

Tālākais uzskatāmi parāda, ka atkarībā no tā, kā mēra laiku un darbu, miljonu mapju var izdzēst acumirklī vai tikai vairākās dienās:

  1. Ja zinat, ko likt dzēst, komandas ievade prasa tikai sekundi4.
  2. Ja nezinat, kur ko dzēst, tad meklēšanā un risināšana — stundu.
  3. Ja skaita tikai servera laiku mapju dzēšanai — divas stundas.
  4. Ja skaita problēmas risināšanā patērēto darbu kopā ar garlaikošanos, gaidot komandu rezultātus (un fonā darot ko citu) — 4 stundas.
  5. Ja skaita problēmas risināšanas sākumu līdz tās pilnīgai atrisināšanai nākamajā dienā — 14 stundas.
  6. Ja skaita laiku no pirmā Munin saņemtā problēmas ziņojuma un problēmas atrisināšanai — trīs dienas.

  1. ^ Piemēram, 32-bitu Windows ar FAT32 failu sistēmu, maksimālais failu skaits var būt tikai daži simti tūkstošu failu, ar ko serverim dažkārt var pietrūkt.
  2. ^ Šeit un turpmāk, praktiski visas komandas ir pildītas ar root lietotāja tiesībām.
  3. ^ Meklējot vainas vienmēr jāpamana, kad vērts pārtraukt "rakt" vienā izvēlētajā virzienā, jo var gadīties, ka vaina nav tur, un ir "jārok" kaut kur citur.
  4. ^ Pirms komandas apstiprināšanas tiek stingri rekomendēts to pārlasīt un apdomāt vismaz dažas sekundes.
Created by Valdis Vītoliņš on 2020-06-08 22:18
Last modified by Valdis Vītoliņš on 2020-06-10 21:41
 
Xwiki Powered
Creative Commons Attribution 3.0 Unported License