Разбор Crab Mysqldump2Git
Различия
Здесь показаны различия между двумя версиями данной страницы.
| Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
|
правила_разработки:как_надо_делать:разбор_crab_mysqldump2git [03.09.2018 06:11] admin |
правила_разработки:как_надо_делать:разбор_crab_mysqldump2git [20.05.2019 15:18] (текущий) |
||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| - | ===== TODO НЕ доделано Разбираем и правим до идеала, спрашиваем все, что непонятно ===== | + | ===== Правим до идеала, спрашиваем все, что непонятно===== |
| - | Все неверные решения добавляем в комменты и потом уже правим | + | Все неверные решения добавляем в комменты и потом уже правим\\ |
| <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 "Example: backup: $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;' | ||
| Строка 14: | Строка 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 | ||
| Строка 39: | Строка 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) объекта | ||
| Строка 75: | Строка 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 "Example: backup: $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;' | ||
| Строка 86: | Строка 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 | ||
| Строка 122: | Строка 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 | ||
| } | } | ||
| Строка 129: | Строка 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; } | + | |
| - | + | ||
| - | ### КОМАНДА №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 | 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~~ | ||