Статьи

Оставаться сухим с помощью косвенных ссылок Bash

Я должен начать этот пост, сказав, что я не рекомендую этот метод для всех ситуаций из-за потенциальных проблем безопасности, а также некоторых компромиссов читаемости. Если это вас не пугает, продолжайте читать.

Недавно я столкнулся с ситуацией, когда мне нужно было обновить скрипт-клон MySQL, написанный на bash, для извлечения данных с нескольких серверов MySQL и записи на один сервер. Мы часто делаем это для быстрого копирования данных из одной среды в другую для тестирования. Оригинальный сценарий был написан с предположением об одном исходном сервере и выглядел примерно так:

source_mysql_host="not.the.best.idea"
source_mysql_user="xxx"
source_mysql_passwd="yyy"
 
echo ; echo " ==>  Cloning databases. Source: $source_mysql_host, Destination: $dest_mysql_host"
 
DATABASES=`mysql -u${source_mysql_user} "-p${source_mysql_passwd}" -h${source_mysql_host} \
            -NBe 'show databases' | egrep -v '^information_schema|performance_schema|mysql|test|backups$'`
for db in $DATABASES; do
    echo "   ==> Cloning database '$db' .. "
 
    $mysqldump_cmd -u${source_mysql_user} "-p${source_mysql_passwd}" -h${source_mysql_host} --add-drop-database --database ${db} | \
    mysql -u${dest_mysql_user} "-p${dest_mysql_passwd}" -h${dest_mysql_host}
done

(Полный блок кода состоял из 26 строк. Многое было пропущено, так как не относится к этой статье)

Чтобы обновить этот скрипт для клонирования данных с нескольких серверов, мы могли бы просто продублировать весь блок кода из 26 строк и изменить переменные так, чтобы первый блок использовал $ OLAP_mysql_host, а другой — $ OLTP_mysql_host и т. Д., Но это не быть очень DRY .

В итоге я обернул блок кода в новый цикл for и использовал косвенные ссылки bash для переключения между исходными серверами MySQL. Обратите внимание на уродливые косвенные ссылки bash. Это работает, и мы остаемся сухими. Стоило ли это? Может быть, может и нет. знак равно

OLTP_source_mysql_host="not.the.best.idea"
OLTP_source_mysql_user="xxx"
OLTP_source_mysql_passwd="yyy"
 
OLAP_source_mysql_host="not.the.best.idea.2"
OLAP_source_mysql_user="xxx"
OLAP_source_mysql_passwd="yyy"
 
for type in "OLTP" "OLAP"; do
 
    # use bash's indirect references. very ugly, but helps us stay DRY
    _mysql_source_host=$(eval "echo \$$(echo ${type}_source_mysql_host)")
    _mysql_source_user=$(eval "echo \$$(echo ${type}_source_mysql_user)")
    _mysql_source_passwd=$(eval "echo \$$(echo ${type}_source_mysql_passwd)")
    _schema_only_tables=$(eval "echo \$$(echo ${type}_SCHEMA_ONLY_TABLES)")
 
    echo ; echo " ==> Cloning ${type} databases. Source: $_mysql_source_host, Destination: $dest_mysql_host"
 
    # get a list of databases, excluding the mysql system db's (ie: mysql, test, ...)
    DATABASES=`mysql -u${_mysql_source_user} "-p${_mysql_source_passwd}" -h${_mysql_source_host} \
                -NBe 'show databases' | egrep -v '^information_schema|performance_schema|mysql|test|backups$'`
    for db in $DATABASES; do
        echo "   ==> Cloning database '$db' .. "
 
        $mysqldump_cmd -u${_mysql_source_user} "-p${_mysql_source_passwd}" -h${_mysql_source_host} --add-drop-database --database ${db} | \
        mysql -u${dest_mysql_user} "-p${dest_mysql_passwd}" -h${dest_mysql_host}
    done
done