Linuxda fayllarni o’chirish uchun juda ko’plab alternativ buyruqlar mavjud. Agarda siz kam hajmdagi fayllar bilan ishlasangiz ushbu utilitalarning o’zi yetib ortadi. Lekin kattaroq hajm uchun alohida yechim talab qilinishi aniq.
Amaliyot bo’yicha tushuntiradigan bo’lsam men texnik xizmat ko’rsatadigan loyihalarning birida auditoriya soni anchagina katta. Shu sababli serverga tushadigan so’rovlarni optimizatsiya qilish uchun bir necha turdagi keshlash prinsiplaridan foydalanganman. Masalan ulardan veb sahifadagi yarim dinamik qismlar va ma’lumotlar bazasidan keladigan select so’rovlar javobini maxsus binary fayllarga yozish hisoblanadi. Lekin, lekin… Kesh fayllar hajmi oshgani sayin ularni tozalash ham o’ziga yarasha muammolar tug’diradi. Masalan mendagi holatda bir kunlik kesh fayllar hajmi 40 gigabaytga teng. Ya’ni maksimal 50 kilobayt fayllardan tashkil topgan millionga yaqin fayllar.
Odatda fayllarni rekursiv shaklda o’chirish uchun linuxda rm va va find utilitalari ishlatiladi.
Misol:
rm -R /cache/*
find /cache -type f -delete
Lekin yuqoridagi har ikki usul avvalo fayllarni rekursiv shaklda tekshirib chiqqani va har bir faylning joylashuvini stdoutga yo’naltirgani sababli o’chirish jarayoni juda ham cho’ziladi. Medagi holatda find uchun bir daqiqadan ko’proq. Rm utilita esa bunday katta hajmdagi fayllani o’chira olmaydi (stdin uchun max 128kb).
Yechim:
Yechim oddiy, C dasturlash tilida streamga yo’naltirilmaydigan qilib kichik utilita yozish. Shuningdek readdir() funksiyasidan foydalanish. Readdir qulayliklaridan biri ro’yxatni xotiraga ko’chirmaydi, bu esa sizda vaqtdan yanada yurish imkonini berishadi.
Ishni feyk fayllardan boshlasak. Jarayonni kuzatish uchun bizga albatta katta hajmdagi fayllarni kerak bo’ladi. Bu uchun esa linuxdagi dd utilitasi orqali /dev/random yordamida feyk fayllar generatsiya qilamiz.
#!/bin/bash
for (( i=0; i <= 1000; ++i ))
do
tmpfile=$(mktemp /tmp/fake/abc-script.XXXXXXXXXXXXXXXXXXXXXXXXXX)
dd if=/dev/urandom of=$tmpfile bs=1M count=$(expr 1 + $RANDOM % 3)
done
Keyingi navbat asosiy o’chirish mexanizmiga:
int main(const int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Papka kiritilmadi!\n");
return -1;
}
int all_files = remove_dir_contents( argv[1], false );
printf("O'chirilgan fayllar: %d\n", all_files);
return(0);
}
Yuqoridagi koddan ko’radigan bo’lsak utilitamiz uchun argument sifatida kerakli papkla berilmoqda. Shundan so’ng remove_dir_contents()funksiyasiga murojaat qilib fayllar o’chirilmoqda. Funksiya esa javob sifatida o’chirilgan fayllar sonini qaytaradi.
Rekursiv jarayonda yana bir holatni hisobga olishimizga to’g’ri keladi. Kiritilgan papka ichida papkalar va fayllar joylashgan bo’lishi mumkin. Agarda sikl ichida fayl kelsa uni shunchaki o’chirish uchun belgilaymiz. Papka holatida esa foydalanuvchi tomonidan berilgan birinchi papka va siklda kelgan papka nomini birlashtirib remove_dir_contents()funskiyasiga qayta argument bilan murojaat qilish lozim. C tezkor dasturlash tili bo’lgani bilan juda ham aqlli emas :) Shu sababli bizga qo’shimcha ikkita matnni bir biriga qo’shib oluvchi funksiya ham kerak bo’ladi .
char *concat(const char *a, const char *b) {
int lena = strlen(a);
int lenb = strlen(b);
char *con = malloc(lena+lenb+1);
memcpy(con,a,lena);
memcpy(con+lena,b,lenb+1);
return con;
}
Qolgani esa oddiy. Readdir orqali papkani o’qiymiz, sikl orqali kerakli amalni bajaramiz.
int remove_dir_contents(char* path, bool selfd){
DIR *d;
struct dirent *dir;
d = opendir( path );
int x = 0;
if ( d ) {
while ( ( dir = readdir( d ) ) != NULL) {
if ( dir->d_name[0] '.' || dir->d_type DT_CHR ) {
continue;
}else {
char* fullpath = concat("/", dir->d_name);
fullpath = concat(path, fullpath);
if ( dir->d_type == DT_DIR ) {
x = x + remove_dir_contents( fullpath, true );
if ( rmdir( fullpath ) != 0){
printf( "Papkani o'chirishda xatolik: %s\n", fullpath );
}else{
x++;
}
}else{
if ( unlink( fullpath ) != 0){
printf( "Faylni o'chirishda xatolik: %s\n", fullpath );
}else{
x++;
}
}
free(fullpath);
}
}
closedir(d);
}
return x;
}
Oldimizda faylni kompiliyatsiya qilish va ishga tushirish sharti qoldi xolos.
gcc -std=c99 -g remover.c -o remover
// Feyk fayllarni generatsiya qilish olish
bash fake.sh
// Feyk fayllarni o'chirish
./remover /tmp/fake
Natija:
Kodlarni to’liq holatda ko’chirib olish:
Katta oqimdagi fayllarni tezkor o'chirish dasturi
Unix asosida ishlovchi rm va find -delete funksiyalari kattaroq hajmdagi fayllar sonida muammo chiqarishi ko'pchilik amaliyotida kuzatilgan. Yuqoridagi C kod aynan shu muammoni bartaraf etish va tmp fayllarni kerakli papkalardan tozalash uchun qo'l keladi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters