Налаштовуючи бекап чергового сайту, зауважив що частина архівів бита. Дуже сильно здивувався такому сюрпризу. Вивчивши ситуацію, знайшов в чому справа ...
Перш за все потрібно коротко розповісти як працюють бекапи у мене:
- На сервері з сайтами, за визначеним розкладом запускається bash скрипт
- В скрипті робиться дамп бази, архівується папка сайту і при необхідності різні доп. файли (наприклад крони).
- До іменам отриманих файлів додається мітка часу і все це складається в бекап-папку відповідного сайту
- Далі, файли копіюються на віддалений сервер за допомогою утиліти ftp
- І наостанок чистимо папку з резервних копій, щоб на вихідному сервері зберігати тільки кілька останніх версій бекапа
Як і написано, система бекапа робить кілька архівів (мінімум 2-а: база + папка сайту). Так ось на сервері бекапов, я виявив що деякі архіви відкривається нормально (видно лістинг файлів), а частина пошкоджена. Саме те, що частина архівів була в нормі мене і ввело в ступор. Пошкоджений файл мав приблизно той же розмір що і на вихідному сервері, при цьому на вихідному сервері файл не був пошкоджений. Саме тому я запідозрив в некоректній роботі безпосередньо ftp передачу між серверами.
Проблема виявилася досить проста: кілька місяців тому, я перенаправив все бекапи на сервер з ОС Windows Server. Відповідно, і FTP сервер був піднятий рідний для Windows Server. Трохи погуглити, я дізнався наступне: при ASCII передачі з Linux сервера на Windows, по-різному обробляється переклад каретки (переклад рядка). Linux передає "\ n", Windows використовує "\ r \ n". Відповідно файл ламається.
Тепер давайте розберемося, чому частина файлів билася, а частина немає. В архівах, де всередині був один єдиний файл (наприклад дамп бази), архіватор міг прочитати ім'я файлу і показати його мені. В архівах де було кілька файлів, архіватор не можу прочитати другий файл і тому відразу повідомляв про помилку. Ну, а по суті при спробі розпакувати архів помилка була в обох випадках. Тобто враховуйте те, що якщо архіватор (WinRar, 7Zip) відкрив архів і ви бачите ім'я файлу, це ще не означає що архів цілий.
Гаразд, думаю ви вже зрозуміли, що я отримав багато битих архівів. Пошукавши рішення, я натрапив на пост, в якому описується ситуація схожа на мою, але найголовніше там описувалося як відновити такі файли. Зробити це досить просто:
для Windows
- Качаємо файлик: http://www.gzip.org/fixgz.zip або звідси
- Разархівіруем, знаходимо утиліту: fixgz.exe
- Далі передаємо їй битий файл і отримуємо відремонтований
- Синтаксис команди: # fixgz broken.gz fixed.gz, де broken.gz = битий файл, fixed.gz = файл куди буде записаний відремонтований
- Я поклав цей файлик fixgz.exe в C: \ Windows, далі пройшовся по проблемним файлів і все відновив
для Linux
- Качаємо файлик: http://www.gzip.org/fixgz.zip або звідси
- розпаковуємо
- Відкриваємо в редакторі: fixgz.c і додаємо наступній рядком "#include <stdlib.h>" після "#include <stdio.h>" (інакше при компіляції будуть warning-і)
- Далі компілюємо файл: # gcc -o fixgz fixgz.c
(при необхідності спочатку встановіть gcc: # apt-get install gcc або #yum install gcc) - У підсумку, в цій директорії повинен з'явитися бінарний файл fixgz, його і використовуємо
- Передаємо битий файл і отримуємо відремонтований
- Синтаксис команди: # fixgz broken.gz fixed.gz, де broken.gz = битий файл, fixed.gz = файл куди буде записаний відремонтований
Тепер треба розібратися як же поправити bash скрипт, щоб файліки відправлятися не биті? У цьому нам допоможе мануал на утиліту ftp, який можна знайти тут: man ftp , Нас цікавить ось ця частина, де описуються команди, доступні після установки з'єднання:
binary - Встановлює режим передачі файлів для підтримки передачі двійкових образів.
Додаємо цю команду перед командою put, вийде щось типу:
ftp - i - n $ HOST $ PORT << EOF
user $ USER $ PASS
binary
put $ SRC _ FILE $ DEST_FILE
bye
EOF
Після цього все починає працювати так, як і очікувалося.