自動化配置iOS開發(fā)環(huán)境

前言:最近公司讓我寫個(gè)自動簽名的教程出來,方便后面培訓(xùn)實(shí)習(xí)生,剛開始我也是老老實(shí)實(shí)的寫的,但令我萬萬沒想到的是第一版交出去后,領(lǐng)導(dǎo)直接給我打回來了,說我寫的他看得懂,實(shí)習(xí)生不一定就能看得懂,尤其是讓我把配置開發(fā)環(huán)境這些都要一步一步的寫出來,還要配上貼圖,讓我寫的再詳細(xì)點(diǎn),好吧,盡管心里不愿意,但手上可還是很誠實(shí)的開始寫上了,然后我想,如果按照領(lǐng)導(dǎo)的要求來寫,那的寫到猴年馬月啊,而且寫的越多,說不定到時(shí)候改的也就越多,于是,我就想到了寫個(gè)腳本來自動化配置開發(fā)環(huán)境,說干就干,經(jīng)過一通鼓搗,一個(gè)強(qiáng)大的自動化配置iOS開發(fā)環(huán)境的腳本就誕生了...

這個(gè)腳本支持安裝Homebrew、GPG/GPG2、RVM、Ruby、CocoaPods、SVN(SVN是否安裝請根據(jù)自己實(shí)際需求來決定,不需要的可以注釋掉。)

使用方法,例如將腳本命名為AutoConfig.py, 則終端中直接CD到腳本所在目錄,然后輸入命令 python3 AutoConfig.py,接著按照提示一步一步安裝即可。

在這里給大家推薦幾個(gè)我寫的工具,如果大家覺得不錯(cuò)的話,請給顆鼓勵的小星星哦...

import os
import re
import sys
import subprocess
from shutil import which

# 用戶配置信息
CONFIG = {
    'gpg_key': None, # 設(shè)置為 None 以自動生成并獲取GPG key,或者指定 GPG key
    'gpg_username': '你的名字',
    'gpg_email': 'nn@aliyun.com',
    'gpg_comment': 'comment is null',
    'gpg_passphrase': 'GPGPWD', # 設(shè)置GPG密鑰的密碼
    'ruby_install_version': None, # 設(shè)置為 None 以自動獲取最新版本,或者指定版本號
    'homebrew_url_install': 'https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh',
    'homebrew_url_uninstall': 'https://gitee.com/cunkai/HomebrewCN/raw/master/HomebrewUninstall.sh',
    'rubygems_source_remove': 'https://rubygems.org/',
    'rubygems_source_custom': 'https://gems.ruby-china.com/',
    'cocoapods_repo_url': 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git',
    'trunk_path': '~/.cocoapods/repos/trunk',
    'master_path': '~/.cocoapods/repos/master'
}

# 打印并執(zhí)行命令的函數(shù)
def run_command(command, check=True, description=""):
    print(f"{description}")
    result = subprocess.run(command, shell=True)
    if check and result.returncode != 0:
        print(f"{description}時(shí)出錯(cuò): {result.returncode}")
        sys.exit(1)
    print(f"{description}")
    return result

# 詢問并確認(rèn)是否需要安裝指定工具
def check_tool_install(tool=""):
    result = input(f"檢測到您目前尚未安裝 {tool}, 是否需要下載并安裝? (y/n): ").strip().lower()
    if result == 'y':
        return True
    else:
        return False

# 檢查并安裝 Homebrew
def check_and_install_homebrew():
    result = run_command("brew --version", check=False)
    if result.returncode == 0:
        reinstall = input("檢測到已安裝Homebrew,是否需要卸載后重新安裝最新版本? (y/n): ").strip().lower()
        if reinstall == 'y':
            run_command(f"/bin/zsh -c \"$(curl -fsSL {CONFIG['homebrew_url_uninstall']})\"", description="卸載 Homebrew")
            run_command(f"/bin/zsh -c \"$(curl -fsSL {CONFIG['homebrew_url_install']})\"", description="重新安裝 Homebrew")
    else:
        if check_tool_install("Homebrew"):
            run_command(f"/bin/zsh -c \"$(curl -fsSL {CONFIG['homebrew_url_install']})\"", description="安裝 Homebrew")

# 檢查 Homebrew 是否安裝,若未安裝則不執(zhí)行后續(xù)安裝
def check_homebrew_installed():
    try:
        run_command("brew --version")
        return True
    except subprocess.CalledProcessError:
        return False

# 檢查并安裝 GPG
def check_and_install_gpg():
    if check_homebrew_installed():
        result = run_command("gpg2 --version", check=False)
        if result.returncode == 0:
            reinstall = input("檢測到已安裝gpg2, 是否需要卸載后重新安裝最新版本? (y/n): ").strip().lower()
            if reinstall == 'y':
                run_command("brew uninstall --force gpg2",description="卸載GPG/GPG2")
                install_gpg()
        else:
            if check_tool_install("GPG"):
                install_gpg()
    else:
        print("Homebrew 未正確安裝,請先安裝 Homebrew")
        sys.exit(1)

def install_gpg():
    run_command("brew install gnupg gnupg2", description="安裝GPG2")

    # 創(chuàng)建符號鏈接
    if not which("gpg2"):
        print("gpg2 命令不可用,嘗試創(chuàng)建符號鏈接...")
        gpg_path = which("gpg")
        if gpg_path:
            # 創(chuàng)建符號鏈接
            run_command(f"ln -s {gpg_path} {gpg_path}2", description="創(chuàng)建符號鏈接")
        else:
            print("gpg2 未找到,請檢查您的系統(tǒng)環(huán)境")
            sys.exit(1)

    # 檢查 GPG2 是否安裝成功
    if check_gpg_installed():
        print("GPG2 安裝成功")
        gpg_key = get_gpg_key()
        command = f"gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys {gpg_key}"
        run_command(command, check=False, description=f"設(shè)置 gpg key {gpg_key}")
    else:
        print("GPG2 安裝失敗,請檢查安裝過程中是否有錯(cuò)誤或網(wǎng)絡(luò)連接是否正常")
        sys.exit(1)

def get_gpg_key():
    """
    生成并返回新的 GPG 密鑰對的公鑰
    """
    if CONFIG['gpg_key']:
        return CONFIG['gpg_key']

    key_list = get_gpg_key_list()
    if len(key_list) >= 2:
        gpg_key = f"{key_list[0]} {key_list[1]}"
        return gpg_key

    key_details = f"""
        %echo Generating a basic OpenPGP key
        Key-Type: RSA
        Key-Length: 2048
        Subkey-Type: RSA
        Subkey-Length: 2048
        Name-Real: {CONFIG['gpg_username']}
        Name-Comment: {CONFIG['gpg_comment']}
        Name-Email: {CONFIG['gpg_email']}
        Expire-Date: 0
        Passphrase: {CONFIG['gpg_passphrase']}
        %commit
        %echo done
    """

    # 將密鑰詳情寫入臨時(shí)文件
    with open('gpg_key_details.txt', 'w') as f:
        f.write(key_details)

    # 生成 GPG 密鑰對
    run_command("gpg2 --batch --generate-key gpg_key_details.txt", description="生成 GPG 密鑰對")

    # 獲取生成的 GPG 密鑰 ID
    result = subprocess.run(
        ["gpg2", "--list-secret-keys", "--keyid-format", "LONG", CONFIG['gpg_email']],
        capture_output=True,
        text=True
    )

    key_output = result.stdout
    gpg_key_id = None

    # 提取 GPG key ID
    for line in key_output.split('\n'):
        if 'sec' in line and '/' in line:
            gpg_key_id = line.split('/')[1].split()[0]
            break

    if not gpg_key_id:
        print("GPG 密鑰生成失敗,請檢查安裝過程中是否有錯(cuò)誤或配置是否正確")
        sys.exit(1)

    # 導(dǎo)出公鑰
    result = subprocess.run(
        ["gpg2", "--armor", "--export", gpg_key_id],
        capture_output=True,
        text=True
    )

    gpg_public_key = result.stdout

    if not gpg_public_key:
        print("GPG 公鑰導(dǎo)出失敗,請檢查安裝過程中是否有錯(cuò)誤")
        sys.exit(1)

    # 刪除臨時(shí)文件
    os.remove('gpg_key_details.txt')

    keys = get_gpg_key_list()

    if len(keys) < 2:
        # 獲取到的 gpg keys 數(shù)量不足
        get_gpg_key()

    gpg_key = f"{keys[0]} {keys[1]}"

    return gpg_key

# 獲取 gpg key列表
def get_gpg_key_list():

    # 查看key列表
    list_keys_result = subprocess.run(
        ["gpg2", "--list-keys"],
        capture_output=True,
        text=True
    )
    
    # 檢查命令執(zhí)行是否成功
    if list_keys_result.returncode != 0:
        print("獲取gpg keys 失敗")
        sys.exit(1)

    # 命令輸出
    output = list_keys_result.stdout
    # 定義一個(gè)正則表達(dá)式來匹配公鑰ID
    key_id_pattern = re.compile(r'\s+([A-F0-9]+)\s+')
    # 使用正則表達(dá)式查找所有公鑰ID
    key_ids = key_id_pattern.findall(output)

    return key_ids


# 檢查 GPG 是否安裝,若未安裝則不執(zhí)行后續(xù)安裝
def check_gpg_installed():
    try:
        run_command("gpg2 --version")
        return True
    except subprocess.CalledProcessError:
        return False

# 檢查并安裝 RVM
def check_and_install_rvm():
    if check_gpg_installed():
        result = run_command("rvm --version", check=False)
        if result.returncode == 0:
            reinstall = input("檢測到RVM已安裝,是否需要卸載后重新安裝最新版本? (y/n): ").strip().lower()
            if reinstall == 'y':
                install_version = get_rvm_version()
                commands = [
                    f"rvm remove {install_version}",
                    "rvm implode",
                    "curl -L https://get.rvm.io | bash -s stable"
                ]
                for command in commands:
                    run_command(command, description=f"執(zhí)行 {command}")
                install_rvm()
        else:
            if check_tool_install("RVM"):
                install_rvm()
    else:
        print("GPG/GPG2 未正確安裝,請先安裝 GPG/GPG2")
        sys.exit(1)

# 獲取已安裝的 RVM 的版本號
def get_rvm_version():
    result = subprocess.run(
        ["rvm", "--version"],
        capture_output=True,
        text=True
    )
    output = result.stdout.strip()
    version_match = re.search(r'\d+\.\d+(\.\d+)?', output)
    return version_match.group()

def install_rvm():
    """
    安裝 RVM
    """
    rvm_commands = [
        "curl -sSL https://get.rvm.io | bash -s stable",
        "curl -L get.rvm.io | bash -s stable",
        "rvm get master"
    ]
    for command in rvm_commands:
        run_command(command, description=f"安裝 RVM {command.split()[0]}")

# 檢查并安裝 Ruby
def check_and_install_ruby():
    if check_rvm_installed():
        result = run_command("ruby --version", check=False)
        if result.returncode == 0:
            reinstall = input("檢測到Ruby已安裝,是否需要重新安裝最新版本? (y/n): ").strip().lower()
            if reinstall == 'y':
                install_ruby()
        else:
            if check_tool_install("Ruby"):
                install_ruby()
    else:
        print("RVM 未正確安裝,請先安裝 RVM")
        sys.exit(1)

def check_rvm_installed():
    try:
        run_command("rvm --version")
        return True
    except subprocess.CalledProcessError:
        return False

def install_ruby():
    """
    安裝 Ruby 并設(shè)置默認(rèn)版本
    """
    install_version = None
    if CONFIG['ruby_install_version'] is None:
        install_version = get_latest_ruby_version()
        if install_version is None:
            print("未找到可用的 Ruby 版本,請輸入您想安裝的 Ruby 版本號: ")
            install_version = input("Ruby 版本號: ").strip()
        else:
            print(f"安裝最新 Ruby 版本: {install_version}")
    else:
        install_version = CONFIG['ruby_install_version']
        print(f"安裝指定 Ruby 版本: {install_version}")

    run_command(f"rvm install {install_version}", description=f"安裝 Ruby {install_version}")
    run_command(f"rvm use ruby-{install_version} --default", description=f"設(shè)置默認(rèn) Ruby 版本為 {install_version}")

# 獲取 Ruby 最新版本
def get_latest_ruby_version():
    """
    自動獲取 RVM 中最新的 Ruby 版本

    返回:
    str: 最新的 Ruby 版本號,如果獲取失敗則返回 None
    """
    print("正在自動獲取 RVM 中最新的 Ruby 版本...")
    try:
        result = subprocess.run(
            ["rvm", "list", "known"],
            capture_output=True,
            text=True
        )
        output = result.stdout
        print("獲取到的 RVM 輸出:\n", output)

        # 提取版本號的正則表達(dá)式
        version_pattern = re.compile(r'\[ruby-]?(\d+\.\d+\.\d+|\d+\.\d+|\d+)')
        versions = version_pattern.findall(output)
        
        def is_valid_version(version):
            """
            檢查是否為有效的版本號
            """
            try:
                tuple(map(int, re.split(r'\D+', version)))
                return True
            except ValueError:
                return False

        if versions:
            versions = [v for v in versions if is_valid_version(v)]
            versions.sort(key=lambda x: tuple(map(int, re.split(r'\D+', x))), reverse=True)
            return versions[0] if versions else None
        else:
            return None

    except subprocess.CalledProcessError as e:
        print("獲取 Ruby 版本失敗:", e)
        return None

# 檢查并安裝 CocoaPods
def check_and_install_cocoapods():
    if check_ruby_and_rvm_installed():

        result = run_command("pod --version", check=False)
        if result.returncode == 0:
            reinstall = input("檢測到Cocoapods已安裝,是否需要卸載后重新安裝最新版本? (y/n): ").strip().lower()
            if reinstall == 'y':
                run_command("sudo gem uninstall cocoapods", description="卸載Cocoapods")
                run_command("rm -rf ~/.cocoapods/", description="移除 Cocoapods 緩存")
                install_cocoapods()
        else:
            if check_tool_install("CocoaPods"):
                install_cocoapods()
    else:
        sys.exit(1)

def install_cocoapods():
    """
    安裝 CocoaPods
    """
    commands = [
        f"gem sources --remove {CONFIG['rubygems_source_remove']}",
        f"gem sources --add {CONFIG['rubygems_source_custom']}",
        "gem sources -l",
        "sudo gem install -n /usr/local/bin cocoapods"
    ]
    for command in commands:
        run_command(command, description=f"執(zhí)行 {command}")

    # 檢查 CocoaPods 是否安裝成功
    try:
        run_command(["pod", "--version"])
        print("CocoaPods 安裝成功")
    except subprocess.CalledProcessError:
        print("CocoaPods 安裝失敗,請檢查安裝過程中是否有錯(cuò)誤或者網(wǎng)絡(luò)連接是否正常")
        sys.exit(1)

    # 克隆 CocoaPods 倉庫
    repo_url = CONFIG['cocoapods_repo_url']

    # 設(shè)置 Trunk 倉庫存儲地址
    trunk_path = os.path.expanduser(CONFIG['trunk_path'])
    # 檢查 CocoaPods Trunk 倉庫是否已存在
    if os.path.isdir(trunk_path):
        print(f"Cocoapods倉庫 trunk 已存在,跳過克隆 trunk 步驟")
    else:
        add_trunk_command = f"git clone {repo_url} {trunk_path}"
        cocoapods_warehouse_clone("trunk", add_trunk_command, trunk_path, "克隆 CocoaPods trunk 倉庫")

    # 設(shè)置 Master 倉庫存儲地址
    master_path = os.path.expanduser(CONFIG['master_path'])
    # 檢查 CocoaPods Master 倉庫是否已存在
    if os.path.isdir(master_path):
        print(f"Cocoapods倉庫 master 已存在,跳過克隆 master 步驟")
    else:
        add_master_command = f"pod repo add master {repo_url}"
        cocoapods_warehouse_clone("master", add_master_command, master_path, "設(shè)置 CocoaPods Master 源")

# Cocoapods 倉庫克隆
def cocoapods_warehouse_clone(warehouse, command, save_path, description):
    run_command(command, description=description)
    # 檢查 CocoaPods 倉庫是否成功克隆
    if not os.path.isdir(save_path):
        retry = input(f"CocoaPods {warehouse} 倉庫克隆失敗, 是否重試? (y/n): ").strip().lower()
        if retry == 'y':
            cocoapods_warehouse_clone(warehouse, command, save_path, description)
        else:
            print(f"CocoaPods {warehouse} 倉庫克隆失敗,請檢查網(wǎng)絡(luò)連接或倉庫地址是否正確。")
            sys.exit(1)

def check_ruby_and_rvm_installed():
    """
    檢查 Ruby 和 RVM 是否安裝
    """
    rvm_result = run_command("rvm --version", check=False)
    if rvm_result.returncode == 0:
        ruby_result = run_command("ruby --version", check=False)
        if ruby_result.returncode == 0:
            return True
        else:
            print("Ruby 未正確安裝,請先安裝Ruby")
            return False
    else:
        print("RVM 未正確安裝,請先安裝RVM")
        return False

# 檢查并安裝 SVN
def check_and_install_svn():
    if check_homebrew_installed():
        result = run_command("svn --version", check=False)
        if result.returncode == 0:
            reinstall = input("檢測到SVN已安裝,是否需要卸載后重新安裝最新版本? (y/n): ").strip().lower()
            if reinstall == 'y':
                run_command("brew uninstall subversion", description="卸載 SVN")
                run_command("brew install svn", description="重新安裝 SVN")
        else:
            if check_tool_install("SVN"):
                run_command("brew install svn", description="安裝 SVN")
    else:
        print("Homebrew 未正確安裝,請先安裝 Homebrew")
        sys.exit(1)

def main():
    # 安裝 Homebrew
    check_and_install_homebrew()
    # 安裝 GPG
    check_and_install_gpg()
    # 安裝 RVM
    check_and_install_rvm()
    # 安裝 Ruby
    check_and_install_ruby()
    # 安裝 CocoaPods
    check_and_install_cocoapods()
    # 安裝 SVN
    check_and_install_svn()
    print("\niOS開發(fā)環(huán)境已配置(檢查)完畢,可以愉快的擼代碼了...\n")

if __name__ == "__main__":
    main()

如您在使用過程中發(fā)現(xiàn)BUG,或有好的意見建議,可發(fā)郵件至aiguanren@icloud.com聯(lián)系我。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容