Over a million developers have joined DZone.

Staying DRY with Bash Indirect References

DZone's Guide to

Staying DRY with Bash Indirect References

· DevOps Zone
Free Resource

Learn more about how CareerBuilder was able to resolve customer issues 5x faster by using Scalyr, the fastest log management tool on the market. 

I should start this post by saying I don’t recommend this method for all situations due to potential security issues, as well as some readability tradeoffs. If that didn’t scare you off, keep reading.

I was faced recently with a situation where I needed to update a MySQL clone script written in bash to pull data from multiple MySQL servers and write to a single server. We often do this to quickly copy data from environment to another for testing. The original script was written with the assumption of only one source server and looked roughly like this:

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}

(The full block of code was 26 lines. Much of it has been left out since it is not relevant to this article)

In order to update this script to clone data from multiple servers we could simply duplicate the entire 26 line block of code and change the variables so that the first block uses $OLAP_mysql_host and the other uses $OLTP_mysql_host, and so on, but that would not be very DRY.

What I ended up doing was wrapping the block of code into a new for loop and using bash’s indirect references to switch between the source MySQL servers. Note the ugly bash indirect references. It works and we stay DRY. Was it worth it? Maybe, Maybe not. =)

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}

Find out more about how Scalyr built a proprietary database that does not use text indexing for their log management tool, allowing customers to search 1TB of data in under a second. 


Published at DZone with permission of Joe Miller, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}