我被赋予了一项任务,使用序列脚本目录升级 MySQL 5.7 DB,并将它们与 DB 中的版本字段进行比较。
您应该查询数据库,然后将返回的表编号与目录中的脚本进行比较,如果编号低于最高脚本,则执行所有最高脚本。脚本的编号也可能存在间隙
但是我已经创建了解决方案 - 只是我无法让脚本按顺序执行。如果编号有间隙,我的 grep 将拉取另一个共享相同编号的脚本 - 我该如何避免这种情况?
例如,grep 为 6,但它执行 66.update.sql,而不是 6.update.sql
注意;我也知道 if 语句 $CURRENT_DB_VERSION -lt 9 可能是多余的 - 但这是我尝试解决任何脚本中单个整数前面有 0 的问题。
我确实创建了一个脚本版本,其中我只需使用 sort -n | head -1 函数按顺序执行脚本并在执行后删除它们 - 但我无法让脚本在 DB 版本上开始执行 .sql 脚本。
#!/bin/bash
####### Usage check
[[ $# -ne 5 ]] && echo -e "Please provide the SQL scripts directory, username, hostname, database and password \nUSAGE: ./sql_upgrade.sh /directory username hostname dbname password" && exit
####### access / store db information
cd $1
user=$2
host=$3
database=$4
pass=$5
######## DB Version store
mysql -u $user -h $host -p$pass -D $database -e "SELECT version FROM versionTable" > dbvers.out
CURRENT_DB_VERSION=`cat dbvers.out | grep -o '[0-9]\+'`
highest_upgrade_version=`ls $(pwd) | grep -Eo '[0-9]+' | sort -rn | head -n 1 | awk 'NR' | sed 's/^0*//'`
######### create list of scripts and order them
ls $(pwd) | grep .sql | sort -n >> scripts_list.txt
while [[ $CURRENT_DB_VERSION -lt $highest_upgrade_version || $CURRENT_DB_VERSION -eq $highest_upgrade_version ]]
do
next_script_to_execute=`grep -Eo $CURRENT_DB_VERSION scripts_list.txt | sort -n | head -n 1`
if [[ $next_script_to_execute -gt $CURRENT_DB_VERSION || -z $next_script_to_execute ]]
then
((CURRENT_DB_VERSION++))
elif [[ $CURRENT_DB_VERSION -lt 9 ]]
then
for i in $(ls $(pwd) | sort -n| grep -E "^[0]" | grep $CURRENT_DB_VERSION| head -1);
do mysql -u $user -h $host -p$pass -D $database < $i
echo $i "is currently being executed"
((CURRENT_DB_VERSION++))
done
else
for i in $(ls $(pwd) | sed 's/^[1-9]*\+ //' | grep -E $CURRENT_DB_VERSION | sort -n | head -n 1); do mysql -u $user -h $host -p$pass -D $database < $i
((CURRENT_DB_VERSION++))
echo $i "is currently being executed"
done
fi
done
((CURRENT_DB_VERSION--))
echo "Current version of the Database is: "$CURRENT_DB_VERSION
mysql -u $user -h $host -p$pass -D $database -e "UPDATE versionTable SET version = $CURRENT_DB_VERSION"
### cleanup temp files
rm -rf scripts_list.txt
rm -rf dbvers.out
答案1
我认为你把事情复杂化了。
以下是您所需逻辑的最小示例:
CURRENT_DB_VERSION=5
for FILE in `ls -1 |sort -n`
do
FILEVERSION=$(echo $FILE | sed -e 's:^0*::' | sed -e 's/[^0-9]*//g')
echo "Filename: $FILE Version: $FILEVERSION"
if (( $FILEVERSION > $CURRENT_DB_VERSION )); then
echo "File $FILEVERSION is newer version than database $CURRENT_DB_VERSION"
# execute the file here
else
echo "File $FILEVERSION is older or same version as database version $CURRENT_DB_VERSION"
fi
done
答案2
首先:解析 ls 的输出不是一个好主意。Unix 上的文件名可能包含非常糟糕的字符,并且 ls 可能会以您意想不到的方式重写文件名的某些部分。我建议始终使用通配符。
假设您知道开始的版本为 $current_db_version,以及想要停止的版本为 $target_db_version,您可以简单地遍历所有数字并使用 glob 来确定针对该特定版本运行的脚本:
for ver in $(seq "${current_db_version}" "${target_db_version}"); do
echo "Upgrading to ${ver}"
for script in ./${ver}.*.sql; do
echo "Executing ${script}"
test -x "${script}" && "${script}"
done
done