Skip to content

Instantly share code, notes, and snippets.

@Athorcis
Last active September 26, 2016 10:25
Show Gist options
  • Select an option

  • Save Athorcis/c403a0a69732ec2bc2e6 to your computer and use it in GitHub Desktop.

Select an option

Save Athorcis/c403a0a69732ec2bc2e6 to your computer and use it in GitHub Desktop.
#!/bin/bash
declare -A options=(
[save]=0
[sshpass]=1
[progress]=1
[remote_ssh_user]=root
[remote_ssh_host]=
[remote_ssh_port]=22
[remote_sql_username]=root
[remote_sql_password]=
[local_sql_username]=root
[local_sql_password]=
[max_allowed_packet]=33554432
)
if [ -z "$1" ]
then
databases=(<databases_list>)
else
databases=($*)
fi
if [ ${options[sshpass]} -eq 1 ] && [ -z "$(which sshpass)" ]
then
echo sshpass needs to be installed in order to ask ssh password just once.
exit 1
fi
if [ ${options[progress]} -eq 1 ] && [ -z "$(which pv)" ]
then
echo pv needs to be installed in order to show the progression of imports.
fi
base_dir=$(dirname "${BASH_SOURCE[0]}")
options[cache_dir]=$base_dir/sync-database.d
options[save_dir]=${options[cache_dir]}/save
function execute_local_query {
local query=$1
eval "declare -A options="${2#*=}
mysql --host=127.0.0.1 --user=${options[local_sql_username]} --password="${options[local_sql_password]}" --silent --skip-column-names --execute="$query"
return $?
}
function get_max_allowed_packet {
eval "declare -A options="${1#*=}
execute_local_query "SHOW VARIABLES WHERE VARIABLE_NAME = 'max_allowed_packet'" "$(declare -p options)" | awk '{ print $2 }'
return $?
}
function set_max_allowed_packet {
local max_allowed_packet=$1
eval "declare -A options="${2#*=}
execute_local_query "SET GLOBAL max_allowed_packet = $max_allowed_packet" "$(declare -p options)"
return $?
}
function increase_max_allowed_packet {
eval "declare -A options="${1#*=}
if ! original_max_allowed_packet=$(get_max_allowed_packet "$(declare -p options)")
then
echo UNABLE TO RETRIEVE max_allowed_packet
return 1
fi
if [ ${options[max_allowed_packet]} -gt $original_max_allowed_packet ]
then
echo INCREASE max_allowed_packet TO ${options[max_allowed_packet]}
if ! set_max_allowed_packet ${options[max_allowed_packet]} "$(declare -p options)"
then
echo UNABLE TO INCREASE max_allowed_packet
return 1
fi
fi
return 0
}
function restore_max_allowed_packet {
eval "declare -A options="${1#*=}
if [ ${options[max_allowed_packet]} -gt $original_max_allowed_packet ]
then
echo RESTORE max_allowed_packet TO $original_max_allowed_packet
if ! set_max_allowed_packet $original_max_allowed_packet "$(declare -p options)"
then
echo UNABLE TO RESTORE max_allowed_packet
return 1
fi
fi
return 0
}
function dump_local_database {
local dump=$1
local database=$2
eval "declare -A options="${3#*=}
mkdir --parents "$(dirname $dump)"
mysqldump --host=127.0.0.1 --user=${options[local_sql_username]} --password="${options[local_sql_password]}" --databases --add-drop-database $database | gzip --to-stdout > "$dump"
return $?
}
function ask_ssh_remote_password {
eval "declare -A options="${1#*=}
while true
do
echo -n "${options[remote_ssh_user]}@${options[remote_ssh_host]}'s password: "
read -r -s remote_ssh_password
echo
execute_remote_command 'exit' "$(declare -p options)"
local error=$?
if [ $error -eq 6 ]
then
echo Host public key is unknown
fi
if [ $error -ne 5 ]
then
break
fi
done
}
function execute_remote_command {
local command=$1
eval "declare -A options="${2#*=}
if [ ${options[sshpass]} -eq 1 ]
then
if [ -z "$remote_ssh_password" ]
then
ask_ssh_remote_password "$(declare -p options)" 1>&2
fi
sshpass -p "$remote_ssh_password" ssh -p ${options[remote_ssh_port]} ${options[remote_ssh_user]}@${options[remote_ssh_host]} "$command"
else
ssh -p ${options[remote_ssh_port]} ${options[remote_ssh_user]}@${options[remote_ssh_host]} "$command"
fi
return $?
}
function dump_remote_database {
local dump=$1
local database=$2
eval "declare -A options="${3#*=}
mkdir --parents "$(dirname $dump)"
execute_remote_command "mysqldump --host=127.0.0.1 --user=${options[remote_sql_username]} --password=${options[remote_sql_password]} --databases --add-drop-database $database | gzip --to-stdout" "$(declare -p options)" > "$dump"
return $?
}
function import_database {
local dump=$1
local database=$2
eval "declare -A options="${3#*=}
if [ ${options[progress]} -eq 1 ]
then
pv --cursor --name source "$dump" | gunzip --to-stdout | pv --cursor --name gunzip | mysql --host=127.0.0.1 --user=${options[local_sql_username]} --password=${options[local_sql_password]} $database
else
gunzip --to-stdout "$dump" | mysql --host=127.0.0.1 --user=${options[local_sql_username]} --password=${options[local_sql_password]} $database
fi
return $?
}
function save_database {
local database=$1
eval "declare -A options="${2#*=}
local dump=${options[save_dir]}/$database.sql.gz
echo SAVE DATABASE $database
dump_local_database "$dump" $database "$(declare -p options)"
return $?
}
function save_databases {
local databases=($1)
eval "declare -A options="${2#*=}
for database in ${databases[*]}
do
if ! save_database $database "$(declare -p options)"
then
echo UNABLE TO SAVE $database
return 1
fi
done
return 0
}
function restore_database {
local database=$1
eval "declare -A options="${2#*=}
local dump=${options[save_dir]}/$database.sql.gz
echo RESTORE DATABASE $database
import_database "$dump" $database "$(declare -p options)"
return $?
}
function sync_database {
local database=$1
eval "declare -A options="${2#*=}
local dump=${options[cache_dir]}/$database.sql.gz
if [ ! -f "$dump" ]
then
echo DUMP REMOTE $database
if ! dump_remote_database "$dump" $database "$(declare -p options)"
then
echo DUMP REMOTE FAILED
return 1
fi
fi
echo IMPORT DUMP $database
if ! import_database "$dump" $database "$(declare -p options)"
then
return 1
fi
return 0
}
function sync_databases {
local databases=($1)
eval "declare -A options="${2#*=}
if [ ${#databases[*]} -eq 0 ]
then
return 0
fi
local database=${databases[0]}
sync_database $database "$(declare -p options)"
local error=$?
if [ $error -eq 0 ]
then
unset 'databases[0]'
sync_databases "${databases[*]}" "$(declare -p options)"
error=$?
fi
if [ $error -ne 0 ]
then
echo UNABLE TO SYNC $database
if [ ${options[save]} -ne 0 ]
then
if ! restore_database $database "$(declare -p options)"
then
echo UNABLE TO RESTORE $database
fi
fi
return 1
fi
return 0
}
if ! increase_max_allowed_packet "$(declare -p options)"
then
exit 1
fi
if [ ${options[save]} -ne 0 ]
then
save_databases "${databases[*]}" "$(declare -p options)"
save_failed=$?
else
save_failed=0
fi
if [ $save_failed -eq 0 ]
then
sync_databases "${databases[*]}" "$(declare -p options)"
sync_failed=$?
else
sync_failed=$save_failed
fi
restore_max_allowed_packet "$(declare -p options)"
exit $sync_failed
@vallai
Copy link

vallai commented Apr 29, 2016

Bien joué :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment