Laravel Homestead环境下SQL备份自动导入Bash脚本问题求助
解决Laravel Homestead备份数据库自动导入脚本的遍历异常问题
你的脚本遍历SQL文件的逻辑存在两个核心问题,导致无法正常循环处理每个文件:
- 遍历
"*.sql"时添加了双引号,shell不会解析通配符,只会把*.sql当作单个文件名处理,而非匹配所有.sql文件 - 数据库名提取逻辑未做行限制,若文件中存在多行匹配内容,会导致变量包含换行符,破坏输出格式
修正后的脚本
#!/bin/bash dirs=() # 收集所有备份子目录名称 for dir in .backup/mysql_backup/*/; do name=${dir#".backup/mysql_backup/"} name=${name%"/"} dirs+=("$name") done # 获取编号最大的最新备份目录 newest=${dirs[0]} for n in "${dirs[@]}" ; do ((n > newest)) && newest=$n done # 验证备份目录存在性 backup_dir=".backup/mysql_backup/$newest" if [ ! -d "$backup_dir" ]; then echo "错误:备份目录 $backup_dir 不存在" exit 1 fi cd "$backup_dir" # 遍历所有.sql文件并导入 for file in *.sql; do # 跳过无匹配文件的情况 [ ! -f "$file" ] && continue # 提取行首匹配的数据库名,仅取第一行结果 prefix="-- Host: 127.0.0.1 Database: " database=$(sed -n "s/^$prefix//p" "$file" | head -n 1) # 跳过无法提取数据库名的文件 [ -z "$database" ] && { echo "警告:文件 $file 未找到数据库名,跳过"; continue; } echo "正在导入数据库: $database" mysql -u homestead -psecret --port 33060 --host=127.0.0.1 "$database" < "$file" done
关键修改说明
- 修复文件遍历:移除
"*.sql"的双引号,让shell正确解析通配符;增加文件存在性检查,避免无匹配文件时报错 - 优化数据库提取:
- 匹配模式前添加
^,确保只匹配行首的注释行,避免误匹配文件内其他相似字符串 - 用
head -n 1限制只取第一行匹配结果,防止变量包含换行符破坏输出格式
- 匹配模式前添加
- 增强错误处理:添加备份目录存在性检查、数据库名非空判断,避免脚本静默失败
- 解释器调整:将
#!/bin/sh改为#!/bin/bash,确保(( ))等bash特性正常运行
额外安全建议
不要在命令行明文传递密码-psecret,可以创建~/.my.cnf配置文件:
[client] user=homestead password=secret host=127.0.0.1 port=33060
后续执行mysql命令会自动读取该配置,无需在脚本中暴露密码。
内容的提问来源于stack exchange,提问作者linx
相关产品推荐
相关产品推荐

