Разбор Crab Mysqldump2Git

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
правила_разработки:как_надо_делать:разбор_crab_mysqldump2git [03.09.2018 13:18]
admin
правила_разработки:как_надо_делать:разбор_crab_mysqldump2git [20.05.2019 15:18] (текущий)
Строка 1: Строка 1:
 ===== Правим до идеала,​ спрашиваем все, что непонятно===== ===== Правим до идеала,​ спрашиваем все, что непонятно=====
 Все неверные решения добавляем в комменты и потом уже правим\\ Все неверные решения добавляем в комменты и потом уже правим\\
-Внимание скрипт не тестировался в продакш,​ пока идеализируем 
  
 <code bash> <code bash>
 #!/bin/bash #!/bin/bash
-set -euE+
 echo "$0 $@ [$$] START" >&2 echo "$0 $@ [$$] START" >&2
 +set -euE
  
 if [ "​${1:​---help}"​ = "​--help"​ ]; then if [ "​${1:​---help}"​ = "​--help"​ ]; then
-        echo "​Examplebackup: $0 --user=root --password=mypass --host=localhost DB_NAME BACKUP_DIR"​+        echo 'InfoСоздает бекап mysql бд и отправляет его в git origin, таблицы пофайлово'​ 
 +        echo "Usage: $0 --user=root --password=mypass --host=localhost DB_NAME BACKUP_DIR"​
         echo '​Example:​ restore: git log; git checkout;'​         echo '​Example:​ restore: git log; git checkout;'​
         echo '​Example:​ restore: for f in *.sql.*; do cat $f >>​new.sql;​ done;'         echo '​Example:​ restore: for f in *.sql.*; do cat $f >>​new.sql;​ done;'
Строка 22: Строка 23:
 ARG_BACKUP_DIR="​${5}"​ ARG_BACKUP_DIR="​${5}"​
 PREFIX="​${ARG_DB_NAME}.sql"​ PREFIX="​${ARG_DB_NAME}.sql"​
-cd "​$BACKUP_DIR"​ 
-rm -f "​$PREFIX.table."​* 
  
 prepare(){ prepare(){
-        ### Присвоение глобальных переменных и ARG_NAME здесь не делаем,​ делаем в начале скрипта 
         if [ ! -d .git ]; then         if [ ! -d .git ]; then
                 git init .                 git init .
Строка 33: Строка 31:
                 git commit -m init                 git commit -m init
         fi         fi
 +        if git remote show origin; then
 +                git pull origin master
 +        fi
 +        return 0
 } }
  
Строка 44: Строка 46:
                 | csplit -n 4  -s -f"​$PREFIX.table."​ - '/-- Table structure for table/'​ '​{*}'​                 | csplit -n 4  -s -f"​$PREFIX.table."​ - '/-- Table structure for table/'​ '​{*}'​
         set +o pipefail         set +o pipefail
 +        return 0
 } }
  
Строка 58: Строка 61:
  
 git_commit_push(){ git_commit_push(){
 +        local ret
         git add .         git add .
-        ​if ! git status ​| grep -q '​nothing to commit';​ then+        ​ret=$( ​git status ​
 +        if [[ "​$ret"​ != *'​nothing to commit'​* ]]; then
                 git commit -am $(date +%Y-%m-%d_%H-%M)                 git commit -am $(date +%Y-%m-%d_%H-%M)
         fi         fi
         git gc         git gc
         if git remote show origin; then         if git remote show origin; then
-               git pull origin master +                ​git push origin master
-               git push origin master+
         fi         fi
 +        return 0
 } }
  
 main(){ main(){
-        cd "$BACKUP_DIR"+        cd "$ARG_BACKUP_DIR"
         rm -f "​$PREFIX.table."​*         rm -f "​$PREFIX.table."​*
         mysqldump_csplit_per_table         mysqldump_csplit_per_table
         table_split_per_size10MB         table_split_per_size10MB
         git_commit_push         git_commit_push
 +        return 0
 } }
 +main
  
 echo "$0 $@ [$$] SUCCESS"​ >&2 echo "$0 $@ [$$] SUCCESS"​ >&2
- 
 exit 0 exit 0
 </​code>​ </​code>​
Строка 91: Строка 97:
 ### то она должна быть с входными параметрами ### то она должна быть с входными параметрами
  
 +echo "$0 $@ [$$] START" >&2
 ### падаем при любых необработанных ошибках ### падаем при любых необработанных ошибках
 set -euE set -euE
-echo "$0 $@ [$$] START" >&2 
  
- +### Делаем ​--help ​самом верху скрипта тк он же является и инфо о скрипте и сразу понятно,​ что делает скрипт
-### Делаем ​хелп в самом верху скрипта тк он же является и инфо о скрипте и сразу понятно,​ что делает скрипт+
 if [ "​${1:​---help}"​ = "​--help"​ ]; then if [ "​${1:​---help}"​ = "​--help"​ ]; then
-        echo "​Examplebackup: $0 --user=root --password=mypass --host=localhost DB_NAME BACKUP_DIR"​+        echo 'InfoСоздает бекап mysql бд и отправляет его в git origin, таблицы пофайлово'​ 
 +        echo "Usage: $0 --user=root --password=mypass --host=localhost DB_NAME BACKUP_DIR"​
         echo '​Example:​ restore: git log; git checkout;'​         echo '​Example:​ restore: git log; git checkout;'​
         echo '​Example:​ restore: for f in *.sql.*; do cat $f >>​new.sql;​ done;'         echo '​Example:​ restore: for f in *.sql.*; do cat $f >>​new.sql;​ done;'
Строка 105: Строка 110:
         exit 0         exit 0
 fi fi
- 
  
 ### Подготовительная работа ### Подготовительная работа
 ### Подготавливаем глобальные переменные,​ что тождественно приватным property объекта self ### Подготавливаем глобальные переменные,​ что тождественно приватным property объекта self
-### по сути понимаем,​ что $USER - это self.user или crab_mysqldump2git.user +### по сути понимаем,​ что $ARG_USER ​- это self.user или crab_mysqldump2git.user 
-### парсинг ​аргументов не стандартизован, ​для простоты кода ​оставим позиционно зависимый+### все аргументы записываем в ARG_NAME=значениеесли это опция ARG_OPTNAME=TRUE,​ если позиционная в массив ARGV[$ARGC]="​$i"​ 
 + 
 +### стараемся глобальные переменные устанавливать в начале скрипта так удобней для чтения 
 +# self.ARG_USER="​${1/​--user=/​}"​
 ARG_USER="​${1/​--user=/​}"​ ARG_USER="​${1/​--user=/​}"​
 +# self.ARG_PASSWORD="​${2/​--password=/​}"​ и т.д.
 ARG_PASSWORD="​${2/​--password=/​}"​ ARG_PASSWORD="​${2/​--password=/​}"​
 ARG_DB_HOST="​${3/​--host=/​}"​ ARG_DB_HOST="​${3/​--host=/​}"​
Строка 117: Строка 125:
 ARG_BACKUP_DIR="​${5}"​ ARG_BACKUP_DIR="​${5}"​
 PREFIX="​${ARG_DB_NAME}.sql"​ PREFIX="​${ARG_DB_NAME}.sql"​
-cd "​$BACKUP_DIR"​ 
-rm -f "​$PREFIX.table."​* 
  
-### подготовительная работа инициализация каталога при необходимости+### подготовительная работа ​действия, ​инициализация каталога при необходимости ​и тп
 prepare(){ prepare(){
         ### Присвоение глобальных переменных и ARG_NAME здесь не делаем,​ делаем в начале скрипта         ### Присвоение глобальных переменных и ARG_NAME здесь не делаем,​ делаем в начале скрипта
Строка 129: Строка 135:
                 git commit -m init                 git commit -m init
         fi         fi
 +        if git remote show origin; then
 +                git pull origin master
 +        fi
 +        return 0
 } }
  
Строка 134: Строка 144:
 ### Описание пользовательских команд(методов) и функций ### Описание пользовательских команд(методов) и функций
 ### метод может работать с глобальными переменным без входящих значений ### метод может работать с глобальными переменным без входящих значений
-### если эти переменные это атрибут объекта self-script или его CONF_NAME переменные+### если эти переменные это атрибут объекта self-script или его ​ARG_NAME ​CONF_NAME переменные
 ### но если это иные переменные,​ то обязательно делать через входные значения ### но если это иные переменные,​ то обязательно делать через входные значения
-### например Только ​аргументом если мы обрабатываем файлы,+### например ТОЛЬКО ​аргументом если мы обрабатываем файлы ​циклом,
 ### через for file in /​tmp/​mysql/​*;​ do funct_name "​$file";​ done ### через for file in /​tmp/​mysql/​*;​ do funct_name "​$file";​ done
  
 +# self.mysqldump_csplit_per_table()
 mysqldump_csplit_per_table(){ mysqldump_csplit_per_table(){
         set -o pipefail         set -o pipefail
Строка 148: Строка 159:
                 | csplit -n 4  -s -f"​$PREFIX.table."​ - '/-- Table structure for table/'​ '​{*}'​                 | csplit -n 4  -s -f"​$PREFIX.table."​ - '/-- Table structure for table/'​ '​{*}'​
         set +o pipefail         set +o pipefail
 +        return 0
 } }
  
 +# self.table_split_per_size10MB()
 table_split_per_size10MB(){ table_split_per_size10MB(){
         local table=""​         local table=""​
Строка 158: Строка 171:
                 fi                 fi
         done         done
 +### return 0 всегда обязательно,​ иначе вызов функции может упасть тк вернется не ноль после цикла или if,
 +### а код возврата от последней команды даже если мы его обработали и он не приведет к локальному падению
         return 0         return 0
 } }
  
 git_commit_push(){ git_commit_push(){
 +        local ret
         git add .         git add .
-        ​if ! git status ​| grep -q '​nothing to commit';​ then+        ​ret=$( ​git status ​
 +        if [[ "​$ret"​ != *'​nothing to commit'​* ]]; then
                 git commit -am $(date +%Y-%m-%d_%H-%M)                 git commit -am $(date +%Y-%m-%d_%H-%M)
         fi         fi
         git gc         git gc
         if git remote show origin; then         if git remote show origin; then
-               git pull origin master +                ​git push origin master
-               git push origin master+
         fi         fi
 +        return 0
 } }
  
 +### основной алгоритм скрипта,​ это последовательность команд и методов
 +### простейшие команды не выносим в отдельные методы
 main(){ main(){
-        ​cd "$BACKUP_DIR"+### КОМАНДА №1 
 +        ​cd "$ARG_BACKUP_DIR" 
 +### КОМАНДА №2
         rm -f "​$PREFIX.table."​*         rm -f "​$PREFIX.table."​*
 +### КОМАНДА №3 - это Команда-Метод объекта self-script,​ он использует глобальные переменные,​ которые по сути атрибуты объекта self-script и это нормально,​ что мы не передаем параметры
         mysqldump_csplit_per_table         mysqldump_csplit_per_table
 +### КОМАНДА №4 - это Команда-Метод
         table_split_per_size10MB         table_split_per_size10MB
 +### КОМАНДА №5 - это Команда-Метод ​       ​
         git_commit_push         git_commit_push
 +        return 0
 } }
 +main
  
 echo "$0 $@ [$$] SUCCESS"​ >&2 echo "$0 $@ [$$] SUCCESS"​ >&2
 +### exit 0 обязателен потому что, если в конце будет условие или выход из цикла и забудешь написать exit 0, то вернется не ноль и все упадет. Всегда надо делать exit 0 и return 0 и не думать каждый раз - это позволит избежать кучу проблем и освобождает мозг. 
 +### Если нужно вернуть не 0 делаем явно [ $ret != 0 ] && exit $ret
 exit 0 exit 0
 </​code>​ </​code>​
  
-===== Разбор и комменты ===== +{(rater>​id=1|name=правила_разработки:как_надоелать:​разбор_crab_mysqldump2git|type=vote|trace=user|tracedetails=1)}
-<code bash> +
-#!/bin/bash+
  
-### Весь bash скрипт рассматриваем как инстанс объекта crab_mysqldump2git 
-### Глобальные переменные - это атрибуты(property) объекта 
-### функции - это методы объекта,​ либо иногда,​ это аналоги команд OS. 
-### если функция работает с переменной,​ которая не является атрибутом объекта,​ 
-### то она должна быть с входными параметрами 
  
-### падаем при любых необработанных ошибках +~~OWNERAPPROVE~~
-set -euEo pipefail +
-echo "$0 $@ [$$] START" >&​2 +
- +
-if [ "​${1:​---help}"​ = "​--help"​ ]; then +
-        echo "​Example:​ backup: $0 --user=root --password=mypass --host=localhost DB_NAME BACKUP_DIR"​ +
-        echo '​Example:​ restore: git log; git checkout;'​ +
-        echo '​Example:​ restore: for f in *.sql.*; do cat $f >>​new.sql;​ done;'​ +
-        echo '​Example:​ restore: /​usr/​bin/​mysql -uroot -p123  < new.sql'​ +
-        exit 0 +
-fi +
-### Подготовительная работа +
-### Подготавливаем глобальные переменные,​ что тождественно приватным property объекта self +
-### по сути понимаем,​ что $USER - это self.user или crab_mysqldump2git.user +
-### парсинг аргументов не стандартизован,​ для простоты кода оставим позиционно зависимый +
- +
-USER="​${1/​--user=/​}"​ +
-PASSWORD="​${2/​--password=/​}"​ +
-DB_HOST="​${3/​--host=/​}"​ +
-DB_NAME="​${4}"​ +
-BACKUP_DIR="​${5}"​ +
-PREFIX="​${DB_NAME}.sql"​ +
- +
-### подготовительная работа инициализация каталога при необходимости +
-### можно вынести в метод git_check_and_init() +
-if [ ! -d .git ]; then +
-        git init . +
-        echo '​*.sql'​ > .gitignore +
-        git add .gitignore +
-        git commit -m init +
-fi +
- +
-### Описание пользовательских команд(методов) и функций +
-### метод может работать с глобальными переменным без входящих значений +
-### если эти переменные это атрибут объекта self-script или его CONF_NAME переменные +
-### но если это иные переменные,​ то обязательно делать через входные значения +
-### например Только аргументом если мы обрабатываем файлы,​ +
-### через for file in /​tmp/​mysql/​*;​ do funct_name "​$file";​ done +
- +
-mysql_dumpsplit(){ +
-        local table=""​ +
-        for table in "​$PREFIX.table."​*;​ do +
-                if [ $(stat -c %s "​$table"​) -gt $((10*1024*1024)) ]; then +
-                        split -a 4 -d -b 10M "​$table"​ "​$table.split."​ +
-                        rm -f "​$table";​ +
-                fi +
-        done +
-### return 0 всегда обязательно,​ иначе вызов функции может упасть тк вернется не ноль, +
-### а код возврата от последней команды даже если мы его обработали и он не приведет к локальному падению +
-        return 0 +
-+
- +
-### основной алгоритм скрипта,​ это последовательность команд и методов +
-### простейшие команды не выносим в отдельные методы +
- +
-### КОМАНДА №1 +
-cd "​$BACKUP_DIR"​ +
- +
-### КОМАНДА №2  всегда стараемся избежать rm -rf +
-rm -f "​$PREFIX.table."​* +
- +
-### КОМАНДА №3 +
-mysqldump --user="​$USER"​ --host="​$DB_HOST"​ --password="​$PASSWORD"​ \ +
-        --opt -c --databases "​$DB_NAME"​ \ +
-        --skip-quick \ +
-        --add-drop-table --add-drop-database --skip-extended-insert \ +
-        --create-options --single-transaction \ +
-        | csplit -n 4  -s -f"​$PREFIX.table."​ - '/-- Table structure for table/'​ '​{*}'​ +
- +
-### КОМАНДА №4 - это команда-метод он использует глобальные переменные,​ которые по сути атрибуты объекта и это нормально +
-mysql_dumpsplit +
- +
-### КОМАНДА №5 +
-git add . +
- +
-### КОМАНДА №6 пример обработки команды у которой бывает код возврата не ноль, +
-### но при этом это не ошибка std_err='​nothing to commit'​ +
-### это разрешенный и достаточно понятный сахар,​ +
-### мы разрешаем такой сахар, хоть он и нарушает правило,​ что нельзя условие делать без &&​ +
-### другие вариации этой конструкции тоже разрешены +
-error=$( git commit -am $(date +%Y-%m-%d_%H-%M) 2>&1 ) \ +
-        || [[ "​$error"​ == *'​nothing to commit'​* ]] || { echo  "​$error";​ exit 1; } +
- +
-### КОМАНДА №7 +
-git gc +
- +
-### КОМАНДА №8 +
-error=$( git push origin master 2>&1 )\ +
-        || echo "​$error"​ | grep -qm1 'does not appear to be a git repositor'​ \ +
-        || { echo  "​$error";​ exit 1; } +
- +
-echo "$0 $@ [$$] SUCCESS"​ >&​2 +
- +
-### обязательно ставим exit 0,  +
-### Иначе не гарантии кода возврата 0 даже если скрип выполнился успешно +
-### тк скрипт может вернуть НЕ 0, а например последний резалт от grep и тп +
-### даже если мы его отловили +
-### при этом не нужно думать,​ что скрипт всегда вернет 0, +
-### скрипт вернет 0 только если все команды успешно выполнилось. +
-exit 0 +
-</​code>​ +
- +
-{(rater>​id=1|name=правила_разработки:​как_надо_делать:​разбор_crab_mysqldump2git|type=vote|trace=user|tracedetails=1)}+