Сторінки

четвер, 6 жовтня 2011 р.

Cкрипт-пожирач файла

Дуже часто в мене виникає потреба обробляти якийсь файл по рядково. Звичайно тут нема ніякої проблеми, ось код:

#!/bin/bash

cat file.txt | while read line; do
 echo $line
done

Але що робити коли файл меговеликий і його обробка триває декілька хвилин, годин або днів (мається на увазі що кожен рядок з файлу піддається довготривалій обробці)???


Коли що небудь або хто небудь перериває цей процес то це мене дуже бісить. Тому виникла потреба в скрипті який би міг вирізати з файлу той рядок який йому потрібно, тобто з’їдати файл.
А якщо добавити прапорець блокування під час зчитування рядка з файла то цей скрипт набуває зовсім нових властивостей
Переваги такого скрипту:

  • можна легко відновити роботу після переривання
  • можна запустити n-кількість копій, які швидше "з’їдять" файл
  • не треба змінювати коди копій скрипту, всі коди однакові - а кожна копія робить своє

Ось детальний код з коментуванням:

#!/bin/bash


FILE="file-e" # файл-жертва

SIZE=`cat $FILE | wc -l`

# поки розмір файлу не дорівнює 0
while [ "$SIZE" != "0" ]; do 

  LOCK=`head -n 1 lock`; # зчитуєм блокування
  
  if [ "$LOCK" == "0" ]; then 
    echo 1 > lock # якщо розблоковано, блокувати і...
    
     
    SIZE=`cat $FILE | wc -l`
    { IFS= read -r line; cat 
    } < "$FILE" > "tmp_$SIZE" && mv "tmp_$SIZE" "$FILE"
    # ось ці три рядки вище роблять наступне:
    # - зчитують верхній рядок в змінну line
    # - решту файла заноситься в тимчасовий файл
    # - потім тимчасовий файл переміщується в оригінал

   echo 0 > lock # розблоковуєм
   DATE=`date  +%T`
   echo "${DATE} ${line}"
   sleep 1
  else 
    echo "Waiting for UNLOCKING..." 
    # якщо заблоковано, очікування 3 сек
    sleep 3
  fi
  
done;
# і знову на початок циклу, поки файл не закінчиться

А тепер треба перевірити роботу цього пожирача. В якості піддослідного файла-жертви буде файл ось такої структури:

1 string
2 string
3 stirng
...
Який створюється скриптом rst.sh. Менше слів, більше коду:
flashbag@laptop:~/vnc-new$ cat rst.sh
#!/bin/bash
rm -rf file-e
touch file-e
chmod 666 file-e

for i in `seq 1 50`; do 
  echo "${i} string" >> file-e
 done
flashbag@laptop:~/vnc-new$ ./rst.sh
flashbag@laptop:~/vnc-new$ cat file-e
1 string
2 string
3 string
4 string
5 string
6 string

Тепер запускаю 4 копії цього мегопожирача файлів...

Як видно з скріншота кожна копія цього мегопожирача з’їдає один унікальний рядок. Дві копії не можу з’їсти один і той самий рядок. Ще один експеримент на рахунок продовження трапези скрипта після переривання.

Ця стаття не принесе нічого нового в досвід затятих лінуксоїдів, тому що вона розрахована на аматорів-початківців у bash програмуванні. Буду радий почути відгуки :)

Прочитати пост