Git辅助bash脚本,-i指定独立密钥访问远程仓库,并智能判断是否需要使用网络代理

劫持Git命令

在个人配置文件(~/.bash_profile~/.bashrc)中新建一个名为git的函数,注意,此处函数名称必须为git,这样在终端执行git命令时,才会优先调用我们定义好的Bash函数,而不是去调用git可执行文件;

Git同名劫持函数代码:

git() {
    if [ $# -gt 1 ] && [[ "$1" == "-i" ]];then
            /v/bin/git.sh "$@"
            return
    fi
    /usr/bin/git "$@"
}

调用git命令时,默认读取~/.ssh/config文件中配置的对应密钥,你也可以使用-i选项为Git命令指定一个独立的密钥,比如使用以下命令使用git命令克隆你小号的私有仓库:

#-i 指定密钥路径,注意仓库地址要使用ssh协议,如果你使用https协议,此文介绍的操作纯属多余。你直接使用账号和密码即可;
git -i ~/.ssh/seconds_account clone git@github.com:useraaa/private-repo.git

注:因本人自建的可执行脚本与第三方可执行文件均保存在/v/bin/目录下,如果你的实际情况不同,你修改对应的路径以适配你自己的情况!

文件 /v/bin/git.sh 脚本代码:

#!/bin/bash
#文件名:/v/bin/git.sh
#劫持git命令,以便使用独立的SSH密钥(不使用.git/config中配置)访问Git仓库
#适用于同一平台有多个账户的情况(比如你有两个Github账户)
#其中的/v/bin/git2为另一个
 
if [ $# -eq 0 ]; then
    echo "Git wrapper script that can specify an ssh-key file
Usage:
    git.sh -i ssh-key-file git-command
    "
    exit 1
fi
 
# remove temporary file on exit
trap 'rm -f /tmp/.git_ssh.$$' 0
 
if [ "$1" = "-i" ]; then
    SSH_KEY=$2; shift; shift
    echo "ssh -i $SSH_KEY \$@" > /tmp/.git_ssh.$$
    chmod +x /tmp/.git_ssh.$$
    export GIT_SSH=/tmp/.git_ssh.$$
fi
 
# in case the git command is repeated
[ "$1" = "git" ] && shift
 
# Run the git command
#git "$@"

## 修改git外部执行进程为 /v/bin/git2,取代默认/usr/bin/git,以便于自动使用代理
/v/bin/git2 "$@"

文件 /v/bin/git2 脚本代码:

#!/bin/bash
#文件名:/v/bin/git2
## 自动检测是否需要代理环境,并应用
## 代理开启的情况下,使用代理环境变量执行后续git命令
PROXY_ARGS=""
SSH_PROXY=""
IS_GITHUB=0
GITBIN=/usr/bin/git
##是否含有github.com的国外网站域名,仅当克隆国外仓库时使用代理
if [[ $* =~ "github.com" || $* =~ "gitlab.com" || $* =~ "bitbucket.org" ]];then
IS_GITHUB=1
fi

## 判断pull或push的时候是否需要使用代理
if [ ${IS_GITHUB} -eq 0 ] && [[ ! $* =~ ( -h| --help)$ ]] && [[ "$*" =~ ^(.*[ ]+)?(push|pull)([ ]+.*)?$ ]] && [[ $($GITBIN remote -v 2>/dev/null|grep -iE '(github\.com|gitlab\.com|bitbucket\.org)' &>/dev/null&&echo -n "yes") ==  "yes" ]];then
#echo "仓库对了"
IS_GITHUB=1
fi

## ping 检测软路由,看自己是否在家
#ping -w 1 -W 1 -c 1 10.10.10.254 &>/dev/null
## 如果ping不通,且访问的是国外git网址,才进行代理测试
## $GIT_FORCE_PROXY:是否强制GIT使用代理,可以在当前Shell中export GIT_FORCE_PROXY=true表明git强制使用代理
if [ ! -z "$GIT_FORCE_PROXY" ] || ([ ${IS_GITHUB} -eq 1 ] && [[ $(ping -w 1 -W 1 -c 1 10.10.10.254 &>/dev/null||echo "false") == false ]]);
then  
    if [[ "$GIT_FORCE_PROXY" =~ ([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]{2,5} ]]; # $GIT_FORCE_PROXY 指定了代理地址的情况
    then
        _git_ProxyType="socks5://"
        [[ "$GIT_FORCE_PROXY" =~ ^http:// ]] && _git_ProxyType="http://"
        declare -a _git_Proxy
        _git_Proxy=($(echo "$GIT_FORCE_PROXY"|awk -F ':' '{gsub(/(http|socks5):\/\/|\/$/,"");printf $1" "$2;}'))
        nc -v -w 1 ${_git_Proxy[0]} ${_git_Proxy[1]} >/dev/null 2>&1
        if [ $? -ne 0 ];then
            echo -e "$GIT_FORCE_PROXY 代理端口测试失败,中断后续操作...!"
            exit 1
        fi
        echo -e "当前 Git 使用代理 ${_git_ProxyType}${_git_Proxy[0]}:${_git_Proxy[1]} ..."
        if [[ "${_git_ProxyType,,}" == "socks5://" ]];then
            # socks 代理识别:
            PROXY_ARGS="env HTTPS_PROXY=socks5://${_git_Proxy[0]}:${_git_Proxy[1]}/"
            SSH_PROXY="ProxyCommand nc -X 5 -x ${_git_Proxy[0]}:${_git_Proxy[1]} %h %p"
        else
            # http 代理识别:
            PROXY_ARGS="env HTTPS_PROXY=http://${_git_Proxy[0]}:${_git_Proxy[1]}/"
            SSH_PROXY="ProxyCommand connect-proxy -H ${_git_Proxy[0]}:${_git_Proxy[1]} %h %p"
        fi
    else
        #请注意nc命令端口号后面重定向符号前面的空格,必须
        nc -v -w 1 127.0.0.1 1080 >/dev/null 2>&1
        if [ $IS_GITHUB -eq 1 -a $? -eq 0 ];then 
            PROXY_ARGS="env HTTPS_PROXY=socks5://127.0.0.1:1080/"
            SSH_PROXY="ProxyCommand nc -X 5 -x 127.0.0.1:1080 %h %p"
        else
            nc -v -w 1 127.0.0.1 1082 >/dev/null 2>&1
            if [ $IS_GITHUB -eq 1 -a $? -eq 0 ];then
                PROXY_ARGS="env HTTPS_PROXY=socks5://127.0.0.1:1082/"
                #PROXY_ARGS="HTTPS_PROXY=socks5://127.0.0.1:1082/"
                SSH_PROXY="ProxyCommand nc -X 5 -x 127.0.0.1:1082 %h %p"
            fi
        fi
    fi
fi
#echo $PROXY_ARGS
#$PROXY_ARGS git $*
OLD_IFS=$IFS
IFS=$(echo -e "\n")
if [ ! -z "$SSH_PROXY" -a -f "$GIT_SSH" ];then
    sed -i "s/\$@/-o \"${SSH_PROXY}\" \$@/" $GIT_SSH
elif [ ! -z "$SSH_PROXY" ];then
    [ ! -z "$PROXY_ARGS" ] && PROXY_ARGS="${PROXY_ARGS} GIT_SSH_COMMAND=\"/usr/bin/ssh -o \\\"${SSH_PROXY}\\\"\""
    #[ ! -z "$PROXY_ARGS" ] && PROXY_ARGS="${PROXY_ARGS} GIT_SSH_COMMAND=\"/usr/bin/ssh -i ~/.ssh/github_stevingking -o \\\"${SSH_PROXY}\\\"\""
fi

# test echo git_ssh
#echo $GIT_SSH
#[ -f "$GIT_SSH" ] && cat $GIT_SSH

## echo test command
#echo $PROXY_ARGS $GITBIN $@
#$PROXY_ARGS $GITBIN $@
gitOptions=( )
while [ $# -gt 0 ]; #循环处理参数,对非选项参数外加双引号包裹,以便兼容commit内容包含空格的情况
do
    case "$1" in
    -*)
        gitOptions=(${gitOptions[@]} $1)
    ;;
    *)
        gitOptions=(${gitOptions[@]} \"$1\")
    ;;
    esac
    shift
done
#set -x
eval $PROXY_ARGS $GITBIN ${gitOptions[*]}  # <--- 此处使用经过处理的$@参数,便于兼容参数中包含空格的情况;eg:git commit -m "This Commit Include Some Space information"
#eval $PROXY_ARGS $GITBIN $@   
#$PROXY_ARGS $GITBIN $@ # <--- 此行会兼容commit内容有空格的情况,但是无法加载环境变量,XXX=ABC这样的环境变量赋值形式只在交互式环境中生效
#set +x
IFS=$OLD_IFS

#####################################
### 另:Git设置代理的备用方法
:<<EOF
git config --global http.proxy http://127.0.0.1:1080
git config --global https.proxy https://127.0.0.1:1080

git config --global --unset http.proxy
git config --global --unset https.proxy
--------------------

git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'

--------------------
只对github.com
git config --global http.https://github.com.proxy socks5://127.0.0.1:1080

#取消代理
git config --global --unset http.https://github.com.proxy)

----------------
# 如果你的代理走的是sock5 用这个
export ALL_PROXY=socks5://127.0.0.1:1080
或者

# 如果你的代理走的是http 用这个
export ALL_PROXY=http://127.0.0.1:1080

----------------
参考1:https://gist.github.com/evantoli/f8c23a37eb3558ab8765
参考2:https://gist.github.com/laispace/666dd7b27e9116faece6
参考3:https://www.google.com/search?newwindow=1&sxsrf=ALeKk015KzJ8woZnlyvv3MFtJuEQzf_E1A%3A1612373340339&ei=XN0aYMSPFI-U0PEPquOF8A8&q=git+use+proxy&oq=git+use+proxy&gs_lcp=CgZwc3ktYWIQAzICCAAyAggAMgIIADICCAAyAggAMgQIABAeMgQIABAeMgQIABAeMgYIABAFEB4yBggAEAUQHjoECAAQQ1D9ibEDWO2fsQNghaOxA2gAcAF4AIAB6QmIAYAhkgEJMi05LjYtMS4xmAEAoAEBqgEHZ3dzLXdpesABAQ&sclient=psy-ab&ved=0ahUKEwjErcjhns7uAhUPCjQIHapxAf4Q4dUDCA0&uact=5
EOF
posted @ 2022-12-25 02:07  晴云孤魂  阅读(144)  评论(0编辑  收藏  举报