Разбор Crab Mysqldump2Git

Различия

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

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

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
правила_разработки:как_надо_делать:разбор_crab_mysqldump2git [03.09.2018 12:52]
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;'
Строка 16: Строка 17:
 fi fi
  
-USER="​${1/​--user=/​}"​ +ARG_USER="​${1/​--user=/​}"​ 
-PASSWORD="​${2/​--password=/​}"​ +ARG_PASSWORD="​${2/​--password=/​}"​ 
-DB_HOST="​${3/​--host=/​}"​ +ARG_DB_HOST="​${3/​--host=/​}"​ 
-DB_NAME="​${4}"​ +ARG_DB_NAME="​${4}"​ 
-BACKUP_DIR="​${5}"​ +ARG_BACKUP_DIR="​${5}"​ 
-PREFIX="​${DB_NAME}.sql"+PREFIX="​${ARG_DB_NAME}.sql"
  
-if [ ! -d .git ]; then +prepare(){ 
-        git init . +        ​if [ ! -d .git ]; then 
-        echo '​*.sql'​ > .gitignore +                git init . 
-        git add .gitignore +                echo '​*.sql'​ > .gitignore 
-        git commit -m init +                git add .gitignore 
-fi+                git commit -m init 
 +        fi 
 +        if git remote show origin; then 
 +                git pull origin master 
 +        fi 
 +        return 0 
 +
 + 
 +mysqldump_csplit_per_table(){ 
 +        set -o pipefail 
 +        mysqldump --user="​$ARG_USER"​ --host="​$ARG_DB_HOST"​ --password="​$ARG_PASSWORD"​ \ 
 +                --opt -c --databases "​$ARG_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/'​ '​{*}'​ 
 +        set +o pipefail 
 +        return 0 
 +}
  
-mysql_dumpsplit(){+table_split_per_size10MB(){
         local table=""​         local table=""​
         for table in "​$PREFIX.table."​*;​ do         for table in "​$PREFIX.table."​*;​ do
Строка 41: Строка 60:
 } }
  
-cd "$BACKUP_DIR"​ +git_commit_push(){ 
-rm -f "$PREFIX.table."*+        local ret 
 +        git add . 
 +        ret=$( git status ) 
 +        if [[ "$ret" ​!= *'​nothing to commit'​* ]]; then 
 +                git commit -am $(date +%Y-%m-%d_%H-%M) 
 +        fi 
 +        git gc 
 +        if git remote show origin; then 
 +                git push origin master 
 +        fi 
 +        return 0 
 +}
  
-mysqldump --user="​$USER"​ --host="​$DB_HOST"​ --password="​$PASSWORD"​ \ +main(){ 
-        ​--opt -c --databases ​"$DB_NAME" ​\ +        ​cd "$ARG_BACKUP_DIR
-        ​--skip-quick \ +        ​rm -f "​$PREFIX.table."​* 
-        --add-drop-table --add-drop-database --skip-extended-insert \ +        ​mysqldump_csplit_per_table 
-        --create-options --single-transaction \ +        ​table_split_per_size10MB 
-        | csplit -n 4  -s -f"​$PREFIX.table." ​- '/-- Table structure for table/'​ '{*}' +        ​git_commit_push 
-mysql_dumpsplit +        ​return 0 
- +} 
-git add . +main
-error=$( git commit -am $(date +%Y-%m-%d_%H-%M) 2>&1 ) \ +
-        ​|| [[ "​$error"​ == *'​nothing to commit'​* ]] || { echo  "​$error";​ exit 1; } +
-        ​ +
-git gc +
-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 echo "$0 $@ [$$] SUCCESS"​ >&2
- 
 exit 0 exit 0
 </​code>​ </​code>​
  
- +===== Разбор ​скрипта =====
-===== Разбор ​и комменты =====+
 <code bash> <code bash>
 #!/bin/bash #!/bin/bash
- 
 ### Весь bash скрипт рассматриваем как инстанс объекта crab_mysqldump2git ### Весь bash скрипт рассматриваем как инстанс объекта crab_mysqldump2git
 ### Глобальные переменные - это атрибуты(property) объекта ### Глобальные переменные - это атрибуты(property) объекта
Строка 77: Строка 97:
 ### то она должна быть с входными параметрами ### то она должна быть с входными параметрами
  
-### падаем при любых необработанных ошибках 
-set -euEo pipefail 
 echo "$0 $@ [$$] START" >&2 echo "$0 $@ [$$] START" >&2
 +### падаем при любых необработанных ошибках
 +set -euE
  
 +### Делаем --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;'
Строка 88: Строка 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"​
  
-USER="​${1/​--user=/​}"​ +### стараемся глобальные переменные устанавливать в начале скрипта так удобней для чтения 
-PASSWORD="​${2/​--password=/​}"​ +# self.ARG_USER="​${1/​--user=/​}"​ 
-DB_HOST="​${3/​--host=/​}"​ +ARG_USER="​${1/​--user=/​}"​ 
-DB_NAME="​${4}"​ +# self.ARG_PASSWORD="​${2/​--password=/​}"​ и т.д. 
-BACKUP_DIR="​${5}"​ +ARG_PASSWORD="​${2/​--password=/​}"​ 
-PREFIX="​${DB_NAME}.sql"+ARG_DB_HOST="​${3/​--host=/​}"​ 
 +ARG_DB_NAME="​${4}"​ 
 +ARG_BACKUP_DIR="​${5}"​ 
 +PREFIX="​${ARG_DB_NAME}.sql"
  
-### подготовительная работа инициализация каталога при необходимости +### подготовительная работа ​действия, ​инициализация каталога при необходимости ​и тп 
-### можно вынести в метод git_check_and_init() +prepare(){ 
-if [ ! -d .git ]; then +        ​### Присвоение глобальных переменных и ARG_NAME здесь не делаем, делаем в начале скрипта 
-        git init . +        if [ ! -d .git ]; then 
-        echo '​*.sql'​ > .gitignore +                git init . 
-        git add .gitignore +                echo '​*.sql'​ > .gitignore 
-        git commit -m init +                git add .gitignore 
-fi+                git commit -m init 
 +        fi 
 +        if git remote show origin; then 
 +                git pull origin master 
 +        fi 
 +        return 0 
 +}
  
 +### Что такое объектный подход в stronbash
 ### Описание пользовательских команд(методов) и функций ### Описание пользовательских команд(методов) и функций
 ### метод может работать с глобальными переменным без входящих значений ### метод может работать с глобальными переменным без входящих значений
-### если эти переменные это атрибут объекта 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
  
-mysql_dumpsplit(){+# self.mysqldump_csplit_per_table() 
 +mysqldump_csplit_per_table(){ 
 +        set -o pipefail 
 +        mysqldump --user="​$ARG_USER"​ --host="​$ARG_DB_HOST"​ --password="​$ARG_PASSWORD"​ \ 
 +                --opt -c --databases "​$ARG_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/'​ '​{*}'​ 
 +        set +o pipefail 
 +        return 0 
 +
 + 
 +# self.table_split_per_size10MB() 
 +table_split_per_size10MB(){
         local table=""​         local table=""​
         for table in "​$PREFIX.table."​*;​ do         for table in "​$PREFIX.table."​*;​ do
Строка 124: Строка 171:
                 fi                 fi
         done         done
-### return 0 всегда обязательно,​ иначе вызов функции может упасть тк вернется не ноль,+### return 0 всегда обязательно,​ иначе вызов функции может упасть тк вернется не ноль ​после цикла или if,
 ### а код возврата от последней команды даже если мы его обработали и он не приведет к локальному падению ### а код возврата от последней команды даже если мы его обработали и он не приведет к локальному падению
 +        return 0
 +}
 +
 +git_commit_push(){
 +        local ret
 +        git add .
 +        ret=$( git status )
 +        if [[ "​$ret"​ != *'​nothing to commit'​* ]]; then
 +                git commit -am $(date +%Y-%m-%d_%H-%M)
 +        fi
 +        git gc
 +        if git remote show origin; then
 +                git push origin master
 +        fi
         return 0         return 0
 } }
Строка 131: Строка 192:
 ### основной алгоритм скрипта,​ это последовательность команд и методов ### основной алгоритм скрипта,​ это последовательность команд и методов
 ### простейшие команды не выносим в отдельные методы ### простейшие команды не выносим в отдельные методы
 +main(){
 ### КОМАНДА №1 ### КОМАНДА №1
-cd "$BACKUP_DIR" +        ​cd "$ARG_BACKUP_DIR
- +### КОМАНДА №2 
-### КОМАНДА №2  ​всегда стараемся избежать rm -rf +        rm -f "​$PREFIX.table."​* 
-rm -f "​$PREFIX.table."​* +### КОМАНДА №3 - это ​Команда-Метод ​объекта self-script, ​он использует глобальные переменные,​ которые по сути атрибуты объекта ​self-script ​и это нормально, что мы не передаем параметры 
- +        ​mysqldump_csplit_per_table 
-### КОМАНДА №3 +### КОМАНДА №4 - это Команда-Метод 
-mysqldump --user="​$USER"​ --host="​$DB_HOST"​ --password="​$PASSWORD"​ \ +        ​table_split_per_size10MB 
-        --opt -c --databases "​$DB_NAME"​ \ +### КОМАНДА №5 - это Команда-Метод ​       ​ 
-        --skip-quick \ +        ​git_commit_push 
-        --add-drop-table --add-drop-database --skip-extended-insert \ +        ​return 0 
-        --create-options --single-transaction \ +} 
-        | csplit -n 4  -s -f"​$PREFIX.table."​ - '/-- Table structure for table/'​ '​{*}'​ +main
- +
-### КОМАНДА №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; } +
- +
-### КОМАНДА №+
-git gc +
- +
-### КОМАНДА №+
-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 echo "$0 $@ [$$] SUCCESS"​ >&2
- +### exit 0 обязателен потому что, если в конце будет условие или выход из цикла и забудешь написать exit 0, то вернется не ноль ​и все упадет. Всегда надо делать exit 0 и return 0 и не думать каждый раз - это позволит избежать ​кучу проблем ​и освобождает ​мозг. 
-### обязательно ставим exit 0 +### Если нужно ​вернуть не 0 делаем явно ​[ $ret != 0 ] && exit $ret
-### Иначе не гарантии кода возврата 0 даже если скрип ​выполнился ​успешно +
-### тк скрипт может ​вернуть НЕ 0, а например последний резалт от grep и тп +
-### даже если мы его отловили +
-### при этом не нужно думатьчто скрипт всегда вернет 0, +
-### скрипт вернет 0 только если все команды успешно ​выполнилось.+
 exit 0 exit 0
 </​code>​ </​code>​
  
 {(rater>​id=1|name=правила_разработки:​как_надо_делать:​разбор_crab_mysqldump2git|type=vote|trace=user|tracedetails=1)} {(rater>​id=1|name=правила_разработки:​как_надо_делать:​разбор_crab_mysqldump2git|type=vote|trace=user|tracedetails=1)}
 +
 +
 +~~OWNERAPPROVE~~