shell脚本无干扰自动更新本地所有仓库 附macOS下的自动执行方案
我有点收藏癖,平日发现好的仓库喜欢拉一个放在本地,以前用GUI工具一段时间拉一下,而且在日常开发过程中,管理多个Git仓库并保持其同步更新可能会变得繁琐,尤其是当远程仓库的URL或协议发生变化时。手动操作不仅耗时,还容易出错。因此,我们需要一个自动化解决方案,来简化这一过程。
问题
- 多个仓库手动更新困难:频繁切换目录并手动执行
git pull
,容易遗漏某些仓库。 - 远程仓库访问失败:远程仓库的协议或URL可能会发生变化,导致更新失败。
- 不必要的文件占用空间:开发过程中产生的缓存和历史文件会占用磁盘空间。
解决思路
我们可以通过编写一个自动化脚本,批量处理多个Git仓库的更新任务,同时加入对远程仓库的可访问性检查。如果HTTPS协议失败,可以自动切换到Git协议,如果仓库失效或需要登录,则跳过,而不是询问登录或等着让输出账号密码
解决方案
这个Bash脚本实现了以下功能:
- 批量更新Git仓库:通过遍历本地所有的
.git
目录,自动执行git pull
更新操作,确保所有项目始终保持最新。 - 远程仓库状态检测:使用
curl
检测远程仓库的可访问性,自动处理301、302重定向,并根据状态码决定是否执行更新操作。 - 协议切换:如果HTTPS协议无法更新,脚本会尝试切换到Git协议,确保最大限度完成更新任务。
以下是完整的Shell脚本,它会自动查找并更新本地所有Git仓库,你在使用此脚本的时候,记得修改/dev/source/git
路径:
#!/bin/bash
# 定义颜色
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # 无颜色
# 确保凭证永久存储在本地文件中
git config --global credential.helper store
# 切换到目标目录
cd /dev/source/git || { echo -e "${RED}无法切换到目标目录${NC}"; exit 1; }
# 查找所有的.git目录
find . -type d -name ".git" | while read -r git_dir
do
# 切换到.git目录所在的上一级目录
repo_dir=$(dirname "$git_dir")
cd "$repo_dir" || { echo -e "${RED}无法进入目录: $repo_dir,跳过此仓库${NC}"; continue; }
# 获取当前目录路径
CURRENT_DIR=$(pwd)
echo -e "${CYAN}当前路径: $CURRENT_DIR${NC}"
# 检查是否存在.git目录
if [ -d ".git" ]; then
# 获取远程仓库URL
remote_url=$(git config --get remote.origin.url)
# 检查远程仓库是否可访问
http_status=$(curl -I -s -o /dev/null -w "%{http_code}" "$remote_url")
# 仅在状态码为200时进行拉取操作
if [ "$http_status" -eq 200 ]; then
echo -e "${GREEN}远程仓库可访问,状态码: ${http_status},开始拉取更新${NC}"
git pull --quiet
if [ $? -ne 0 ]; then
echo -e "${YELLOW}HTTPS协议拉取失败,尝试使用git协议${NC}"
git_url="${remote_url/https:\/\//git@}"
git_url="${git_url/\//:}"
git remote set-url origin "$git_url"
git pull --quiet
if [ $? -ne 0 ]; then
echo -e "${RED}git协议拉取仍然失败,跳过此仓库${NC}"
else
echo -e "${GREEN}使用git协议更新成功${NC}"
fi
else
echo -e "${GREEN}HTTPS协议更新成功${NC}"
fi
elif [ "$http_status" -eq 301 ] || [ "$http_status" -eq 302 ]; then
# 如果状态码为301或302,则去掉URL末尾的.git再试一次
echo -e "${YELLOW}远程仓库状态码: ${http_status},尝试去掉.git后重新获取状态${NC}"
trimmed_url="${remote_url%.git}"
http_status_trimmed=$(curl -I -s -o /dev/null -w "%{http_code}" "$trimmed_url")
if [ "$http_status_trimmed" -eq 200 ]; then
echo -e "${GREEN}去掉.git后的URL可访问,状态码: ${http_status_trimmed},开始拉取更新${NC}"
git remote set-url origin "$trimmed_url"
git pull --quiet
if [ $? -ne 0 ]; then
echo -e "${RED}发生错误,跳过此仓库${NC}"
else
echo -e "${GREEN}更新成功${NC}"
fi
else
echo -e "${RED}去掉.git后的URL仍不可访问,状态码: ${http_status_trimmed},跳过此仓库${NC}"
fi
else
echo -e "${RED}远程仓库状态码: ${http_status},跳过此仓库${NC}"
fi
else
echo -e "${YELLOW}.git目录不存在,跳过此仓库${NC}"
fi
# 返回上级目录,继续处理下一个.git目录
cd - > /dev/null || { echo -e "${RED}无法返回上级目录,脚本中止${NC}"; exit 1; }
done
exit 0
macOS下定时运行此脚本 使用launchd定时任务
1.创建一个.plist文件来描述定时任务。使用如下内容创建net.lvtao.gitupdate.plist文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>net.lvtao.gitupdate</string>
<key>ProgramArguments</key>
<array>
<string>/dev/source/git/up.sh</string>
</array>
<key>StartInterval</key>
<integer>10800</integer> <!-- 每3小时执行一次,3小时=10800秒 -->
<key>StandardOutPath</key>
<string>/dev/source/git/log.log</string>
<key>StandardErrorPath</key>
<string>/dev/source/git/error.log</string>
</dict>
</plist>
2.将此文件放置在~/Library/LaunchAgents/
目录下,并使用以下命令加载任务:launchctl load ~/Library/LaunchAgents/net.lvtao.gitupdate.plist
好了,这样我们这个脚本就可以每三小时执行一次了
版权声明:本文为原创文章,版权归 全栈开发技术博客 所有。
本文链接:https://www.lvtao.net/tool/git-cron-up-macos-plist.html
转载时须注明出处及本声明