昨天浏览一篇关于脚本的技术文章的时候, 偶然看见一篇文章中写道关于mysql备份的脚本.
但是这个脚本时基于本地的MySQL服务写的, 由于我近年来使用的mysql基本上都是docker部署的,
因此, 我就在想, 如何能把脚本改造成docker部署的服务也能使用的脚本呢?
而我, 作为shell脚本学习的劣等生, 就想到了最近很火的一个技术 ——ChatGPT
嗯, 就觉定是你了
阅读提示
一开始我没想那么多, 就把当时的想法表达出来. 所以问题表述没那么详细, 建议描述问题时尽量详细点.
理论上来说, 描述的越详细, 提供的代码就越规范, 正确率高
可以看到, 真的很神奇, ChatGPT能够基本理解我所提出的问题, 并给我提供了如上图的脚本代码, 而且贴心的为我加上了中文注释. 不仅如此, 在脚本代码提供之后还为我们总结了脚本的过编写核心逻辑
在此特将脚本分享在下面, 方便各位读者尝试
#!/bin/bash
# 定义变量
MYSQL_CONTAINER_NAME="mysql" # MySQL容器的名称
MYSQL_DB_NAME="mydatabase" # MySQL数据库的名称
BACKUP_DIR="/backup/mysql" # 备份文件存放的目录
# 创建备份目录
mkdir -p $BACKUP_DIR
# 获取当前时间
DATETIME=$(date +%!Y(MISSING)%!m(MISSING)%!d(MISSING)%!H(MISSING)%!M(MISSING)%!S(MISSING))
# 备份MySQL数据库
docker exec $MYSQL_CONTAINER_NAME sh -c 'exec mysqldump --databases $MYSQL_DB_NAME -uroot -p"$MYSQL_ROOT_PASSWORD"' > $BACKUP_DIR/$MYSQL_DB_NAME-$DATETIME.sql
# 压缩备份文件
gzip -f $BACKUP_DIR/$MYSQL_DB_NAME-$DATETIME.sql
# 删除7天前的备份文件
find $BACKUP_DIR -type f -name "*.gz" -mtime +7 -delete
唯一美中不足的是有两点
chmod +x 脚本名称
MYSQL_ROOT_PASSWORD
没定义, 需要自己在脚本开头定义下修改上面两点之后执行脚本, 结果仍然执行失败, 错误信息如图所示
我们将执行脚本时出现的错误信息反馈给ChatGPT, 看它如何进行回答
可以看出, ChatGPT确实是根据我的反馈, 对代码进行了适当的修改, 并在结尾说明修改的内容.
我对第10行的单引号改成了双引号,并使用了反斜线来转义双引号,这样就可以在命令替换中使用变量了
为了能够清晰的观察出改动了什么, 这里通过代码比对的工具对两个代码进行比对来查看二者不同
并且在比对的时候, 我突意识到如果按照上面的方式进行全量备份的话, 会十分耗时,
因此, 我决定修改问题条件, 并让ChatGPT重新帮助我编写脚本
将问题再次进行凝练之后, ChatGPT提供的脚本如下
相关代码(这部分代码很重要, 后面还会用到)
#!/bin/bash
# 定义变量
MYSQL_CONTAINER_NAME="mysql" # MySQL容器的名称
BACKUP_DIR="/backup/mysql" # 备份文件存放的目录
# 创建备份目录
mkdir -p $BACKUP_DIR
# 获取当前时间
DATETIME=$(date +%!!(MISSING)Y(MISSING)%!!(MISSING)m(MISSING)%!!(MISSING)d(MISSING)%!!(MISSING)H(MISSING)%!!(MISSING)M(MISSING)%!!(MISSING)S(MISSING))
# 获取MySQL中所有的数据库名称
DATABASES=$(docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD -s -e 'show databases;'")
# 备份每个数据库
for DB_NAME in $DATABASES
do
if [ $DB_NAME != "information_schema" ] && [ $DB_NAME != "performance_schema" ] && [ $DB_NAME != "mysql" ]; then
docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysqldump $DB_NAME -uroot -p\$MYSQL_ROOT_PASSWORD" > $BACKUP_DIR/$DB_NAME-$DATETIME.sql
gzip -f $BACKUP_DIR/$DB_NAME-$DATETIME.sql
find $BACKUP_DIR -type f -name "$DB_NAME*.gz" -mtime +7 -delete
fi
done
这里在代码底部给出了修改的内容
我们来修改下此脚本, 修改变量MYSQL_CONTAINER_NAME
, BACKUP_DIR
和MYSQL_ROOT_PASSWORD
, 然后执行脚本,
可以看到依旧报错, 最明显的错误是 Using a password on the command line interface can be insecure
我们继续将这个问题抛给ChatGPT, 看看它是怎么回答
相关代码
#!/bin/bash
# 定义变量
MYSQL_CONTAINER_NAME="mysql" # MySQL容器的名称
BACKUP_DIR="/backup/mysql" # 备份文件存放的目录
MYSQL_CONFIG_FILE="/root/.my.cnf" # MySQL的配置文件,用于存储用户名和密码
# 创建MySQL的配置文件
echo "[client]" > $MYSQL_CONFIG_FILE
echo "user=root" >> $MYSQL_CONFIG_FILE
echo "password=\$MYSQL_ROOT_PASSWORD" >> $MYSQL_CONFIG_FILE
# 创建备份目录
mkdir -p $BACKUP_DIR
# 获取当前时间
DATETIME=$(date +%!!(MISSING)!(MISSING)Y(MISSING)%!!(MISSING)!(MISSING)m(MISSING)%!!(MISSING)!(MISSING)d(MISSING)%!!(MISSING)!(MISSING)H(MISSING)%!!(MISSING)!(MISSING)M(MISSING)%!!(MISSING)!(MISSING)S(MISSING))
# 获取MySQL中所有的数据库名称
DATABASES=$(docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysql -s -e 'show databases;'")
# 备份每个数据库
for DB_NAME in $DATABASES
do
if [ $DB_NAME != "information_schema" ] && [ $DB_NAME != "performance_schema" ] && [ $DB_NAME != "mysql" ]; then
docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysqldump $DB_NAME" > $BACKUP_DIR/$DB_NAME-$DATETIME.sql
gzip -f $BACKUP_DIR/$DB_NAME-$DATETIME.sql
find $BACKUP_DIR -type f -name "$DB_NAME*.gz" -mtime +7 -delete
fi
done
# 删除MySQL的配置文件
rm $MYSQL_CONFIG_FILE
在新的脚本中,核心就是在原来脚本的基础上创建了一个MySQL账号密码信息的配置文件/root/.my.cnf,
通过将重要信息保存在配置文件来解决上面问题
那么, 我们修改脚本文件中 user, password
信息后, 继续执行如下代码, 可以看到提示账户密码信息不对.
本着尽量多依靠ChatGPT的想法, 继续将代码执行的问题反馈
在提问时, 我试图引诱他往这方面考虑, 我们且看他的回答
相关代码
#!/bin/bash
# 定义变量
MYSQL_CONTAINER_NAME="mysql" # MySQL容器的名称
BACKUP_DIR="/backup/mysql" # 备份文件存放的目录
# 创建备份目录
mkdir -p $BACKUP_DIR
# 获取当前时间
DATETIME=$(date +%!!(MISSING)Y(MISSING)%!!(MISSING)m(MISSING)%!!(MISSING)d(MISSING)%!!(MISSING)H(MISSING)%!!(MISSING)M(MISSING)%!!(MISSING)S(MISSING))
# 获取MySQL中所有的数据库名称
DATABASES=$(docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD -s -e 'show databases;'")
# 备份每个数据库
for DB_NAME in $DATABASES
do
if [ $DB_NAME != "information_schema" ] && [ $DB_NAME != "performance_schema" ] && [ $DB_NAME != "mysql" ]; then
docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysqldump $DB_NAME -uroot -p\$MYSQL_ROOT_PASSWORD" > $BACKUP_DIR/$DB_NAME-$DATETIME.sql
gzip -f $BACKUP_DIR/$DB_NAME-$DATETIME.sql
find $BACKUP_DIR -type f -name "$DB_NAME*.gz" -mtime +7 -delete
fi
done
可以看到, ChatGPT仅仅在三问给出的代码基础上把代码定义成变量, 然后在执行备份命令时加上这些参数,
这种执行方式结果我们可想而知, 依旧是失败
这里我已经发现, 对于ChatGPT来说, 现在是陷入了一个循环: 无论是账号密码定义在脚本最开始定义, 还是在脚本执行时添加, 执行备份的时候都会出现Using a password on the command line interface can be insecure
, 而将问题再次反馈给ChatGPT之后, 就会给出一种将账号密码信息保存成配置文件之后然后执行的脚本解决方案, 但是在执行其给出的脚本执行仍会出现账号密码不正确的情况, 再然后将问题进行反馈, 得到的脚本几乎与最开始的脚本一样.
就这样, 在我继续追问时, ChatGPT竟然"发脾气了", 不允许继续追问了, 没想到你竟然这么高冷 [○・`Д´・ ○]
所以, 我还是打算自己修改下这部分的代码
通过step5的分析, 结合自己的判断可知, 当前脚本最好应从step4的提供的代码开始进行调试. 那么话不多说, 我们开始调试吧.
根据上面脚本执行的报错, 可以看到最明显的错误就是提示账号密码不正确,
而我自己也核对了账号密码也没问题, 于是开始从脚本上面找问题
ChatGPT也描述这段代码的逻辑, 我们再次嚼一下
在这个脚本中,我们创建了一个MySQL的配置文件/root/.my.cnf,并在其中存储了用户名和密码。我们使用echo命令将用户名和密码写入配置文件。然后在使用mysqldump命令备份MySQL数据库时,不再需要在命令行中输入密码,而是使用配置文件中的密码。备份完成后,我们删除了MySQL的配置文件。希望这个修改后的脚本可以帮助你解决这个问题。
而我发现, 在执行备份命令的时候, 是需要进入MySQL的命令行的, 但是我的MySQL是通过docker部署的.
因此需要进入MySQL的docker容器内的命令行才能执行备份命令.
所以, 存储MySQL信息的配置文件只有在docker容器内才可以被发现并执行.
为了验证自己的猜想, 我决定进入MySQL的docker容器中去查看是否有这个配置文件 (其实不用查看,
因为脚本中就不存在复制MySQL信息的配置文件到Docker容器的命令! 但是抱着眼见为实的想法还是进行了验证)
这时, 就需要docker cp命令了, 利用docker cp 来将生成的MySQL信息的配置文件复制到容器中, 修改后代码如下docker cp /目录/文件名 容器id:目录
, 这里需要利用docker ps
命令来获取当前容器的容器id
#!/bin/bash
# 定义变量
MYSQL_CONTAINER_NAME="mysql" # MySQL容器的名称
BACKUP_DIR="/backup/mysql" # 备份文件存放的目录
MYSQL_CONFIG_FILE="/root/.my.cnf" # MySQL的配置文件,用于存储用户名和密码
# 创建MySQL的配置文件
echo "[client]" > $MYSQL_CONFIG_FILE
echo "user=账号" >> $MYSQL_CONFIG_FILE
echo "password=密码" >> $MYSQL_CONFIG_FILE
# 将生成的文件复制到容器中 ( 这里需要注意容器id应改为自己的 )
docker cp /root/.my.cnf cf22ab9c8f17:/root
# 创建备份目录
mkdir -p $BACKUP_DIR
# 获取当前时间
DATETIME=$(date +%!!(MISSING)!(MISSING)Y(MISSING)%!!(MISSING)!(MISSING)m(MISSING)%!!(MISSING)!(MISSING)d(MISSING)%!!(MISSING)!(MISSING)H(MISSING)%!!(MISSING)!(MISSING)M(MISSING)%!!(MISSING)!(MISSING)S(MISSING))
# 获取MySQL中所有的数据库名称
DATABASES=$(docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysql -s -e 'show databases;'")
# 备份每个数据库
for DB_NAME in $DATABASES
do
if [ $DB_NAME != "information_schema" ] && [ $DB_NAME != "performance_schema" ] && [ $DB_NAME != "mysql" ]; then
docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysqldump $DB_NAME" > $BACKUP_DIR/$DB_NAME-$DATETIME.sql
gzip -f $BACKUP_DIR/$DB_NAME-$DATETIME.sql
find $BACKUP_DIR -type f -name "$DB_NAME*.gz" -mtime +7 -delete
fi
done
# 删除MySQL的配置文件
rm $MYSQL_CONFIG_FILE
可以看到执行脚本之后, 仍然给出了警告信息
但是, docker 容器里面已经存在MySQL账号密码信息的配置文件(算是成功了一半)
本着简单的事情问ChatGPT, 复杂的问题自己来解决的思路
继续上面执行的问题交给ChatGPT(没错, 我又偷懒了~)
执行后依然报错, 很容易推测出是转义符号和空格会导致生成备份文件失败,因此我们可以通过-
将日期和时间进行连接
最终代码
#!/bin/bash
# 定义变量
MYSQL_CONTAINER_NAME="mysql" # MySQL容器的名称
BACKUP_DIR="/backup/mysql" # 备份文件存放的目录
MYSQL_CONFIG_FILE="/root/.my.cnf" # MySQL的配置文件,用于存储用户名和密码
# 创建MySQL的配置文件
echo "[client]" > $MYSQL_CONFIG_FILE
echo "user=mysql账号" >> $MYSQL_CONFIG_FILE
echo "password=mysql密码" >> $MYSQL_CONFIG_FILE
# 将生成的文件复制到容器中 ( 这里需要注意容器id应改为自己的 )
docker cp /root/.my.cnf cf22ab9c8f17:/root
# 创建备份目录
mkdir -p $BACKUP_DIR
# 获取当前时间
DATETIME=$(date +%Y-%m-%d-%H:%M:%S)
# 获取MySQL中所有的数据库名称
DATABASES=$(docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysql -s -e 'show databases;'")
# 备份每个数据库
for DB_NAME in $DATABASES
do
if [ $DB_NAME != "information_schema" ] && [ $DB_NAME != "performance_schema" ] && [ $DB_NAME != "mysql" ]; then
docker exec $MYSQL_CONTAINER_NAME sh -c "exec mysqldump $DB_NAME" > $BACKUP_DIR/$DB_NAME-$DATETIME.sql
gzip -f $BACKUP_DIR/$DB_NAME-$DATETIME.sql
find $BACKUP_DIR -type f -name "$DB_NAME*.gz" -mtime +7 -delete
fi
done
# 删除MySQL的配置文件
rm $MYSQL_CONFIG_FILE
在博客写完之后. 又在b站上面了解下ChatGPT, 特此分享下学习到的内容.
ChatGPT的概念
ChatGPT 的基础原理(对应下面三个阶段)
ChatGPT 的三个训练阶段
意义和价值
通过以上对话可以得出结论, ChatGPT虽然已经很智能了, 甚至能够强到会写代码了.
但是, 在很多情况下, 给出的代码往往只是对每个单独功能代码的堆砌(个人感觉).
并且, 因为它自身没有编译器, 无法验证自己提供的代码, 也就是说它无法保证代码的正确性, 健壮性以及并发性,.
因此, AI 当前并不能取代人类进行编码. 但ChatGPT在当下可以作为相关技术领域开发人员提升生产力水平的一个辅助工具. 由ChatGPT来写出代码, 技术人员来进行修改和调试. 最终较为快速的实现代码编写.
或许, 不久的将来, 随着AI技术的成熟, 能够最终实现写出的代码复制即可运行, 并且健壮性以及并发性都能得到保证的代码.
那时候, 可能一些程序员的工作就完全会被替代了…
为了不被淘汰, 我们也要学习拥抱新知识, 去学习如何使用它.
一些新工具的出现可能会淘汰调一批人, 但是却大概率淘汰不了会灵活使用这些新工具的人.
就这样, 在ChatGPT的帮助下, 我以一个外行的身份写完了一个脚本:
实现在docker容器中能够部分mysql指定数据库数据备份
虽然我已经把问题说的尽量简单, 但是一点点的调试确实比较繁琐且费时. 可能是我对ChatGPT不太熟悉的原因
其实后面还可以做成, 开机自启动+每天定时执行脚本功能, 后续有机会我会继续进行分享.
也欢迎大家在评论区相互交流~~~