前言:最近公司让我写个自动签名的教程出来,方便后面培训实习生,刚开始我也是老老实实的写的,但令我万万没想到的是第一版交出去后,领导直接给我打回来了,说我写的他看得懂,实习生不一定就能看得懂,尤其是让我把配置开发环境这些都要一步一步的写出来,还要配上贴图,让我写的再详细点,好吧,尽管心里不愿意,但手上可还是很诚实的开始写上了,然后我想,如果按照领导的要求来写,那的写到猴年马月啊,而且写的越多,说不定到时候改的也就越多,于是,我就想到了写个脚本来自动化配置开发环境,说干就干,经过一通鼓捣,一个强大的自动化配置iOS开发环境的脚本就诞生了...
这个脚本支持安装Homebrew、GPG/GPG2、RVM、Ruby、CocoaPods、SVN(SVN是否安装请根据自己实际需求来决定,不需要的可以注释掉。)
使用方法,例如将脚本命名为AutoConfig.py, 则终端中直接CD到脚本所在目录,然后输入命令 python3 AutoConfig.py,接着按照提示一步一步安装即可。
在这里给大家推荐几个我写的工具,如果大家觉得不错的话,请给颗鼓励的小星星哦...
import os
import re
import sys
import subprocess
from shutil import which
# 用户配置信息
CONFIG = {
'gpg_key': None, # 设置为 None 以自动生成并获取GPG key,或者指定 GPG key
'gpg_username': '你的名字',
'gpg_email': 'nn@aliyun.com',
'gpg_comment': 'comment is null',
'gpg_passphrase': 'GPGPWD', # 设置GPG密钥的密码
'ruby_install_version': None, # 设置为 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'
}
# 打印并执行命令的函数
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}时出错: {result.returncode}")
sys.exit(1)
print(f"{description}")
return result
# 询问并确认是否需要安装指定工具
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 是否安装,若未安装则不执行后续安装
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")
# 创建符号链接
if not which("gpg2"):
print("gpg2 命令不可用,尝试创建符号链接...")
gpg_path = which("gpg")
if gpg_path:
# 创建符号链接
run_command(f"ln -s {gpg_path} {gpg_path}2", description="创建符号链接")
else:
print("gpg2 未找到,请检查您的系统环境")
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"设置 gpg key {gpg_key}")
else:
print("GPG2 安装失败,请检查安装过程中是否有错误或网络连接是否正常")
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
"""
# 将密钥详情写入临时文件
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 密钥生成失败,请检查安装过程中是否有错误或配置是否正确")
sys.exit(1)
# 导出公钥
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 公钥导出失败,请检查安装过程中是否有错误")
sys.exit(1)
# 删除临时文件
os.remove('gpg_key_details.txt')
keys = get_gpg_key_list()
if len(keys) < 2:
# 获取到的 gpg keys 数量不足
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
)
# 检查命令执行是否成功
if list_keys_result.returncode != 0:
print("获取gpg keys 失败")
sys.exit(1)
# 命令输出
output = list_keys_result.stdout
# 定义一个正则表达式来匹配公钥ID
key_id_pattern = re.compile(r'\s+([A-F0-9]+)\s+')
# 使用正则表达式查找所有公钥ID
key_ids = key_id_pattern.findall(output)
return key_ids
# 检查 GPG 是否安装,若未安装则不执行后续安装
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"执行 {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 并设置默认版本
"""
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"设置默认 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)
# 提取版本号的正则表达式
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"执行 {command}")
# 检查 CocoaPods 是否安装成功
try:
run_command(["pod", "--version"])
print("CocoaPods 安装成功")
except subprocess.CalledProcessError:
print("CocoaPods 安装失败,请检查安装过程中是否有错误或者网络连接是否正常")
sys.exit(1)
# 克隆 CocoaPods 仓库
repo_url = CONFIG['cocoapods_repo_url']
# 设置 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 仓库")
# 设置 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, "设置 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} 仓库克隆失败,请检查网络连接或仓库地址是否正确。")
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开发环境已配置(检查)完毕,可以愉快的撸代码了...\n")
if __name__ == "__main__":
main()
如您在使用过程中发现BUG,或有好的意见建议,可发邮件至mobileAppDvlp@icloud.com联系我。