Homebrew 配合 shell 脚本自动安装软件
换电脑很烦恼,最麻烦的就是软件安装和环境配置,环境还好,配置文件复制过来开箱即用,软件着实麻烦,每次都得不停的输入重复命令来安装,痛定思痛,写了个 shell 脚本调用 homebrew 安装软件,从此可以带着 install.sh 随便换机器了。(闲的 🥚 疼,手动 🌹🐔)
也可以使用
Homebrew
自带的备份工具Homebrew Bundle
;
- 备份:
brew bundle dump --describe --force --file="~/xxx/Brewfile"
;- 恢复:
brew bundle --file="~/xxx/Brewfile"
;
XX 叨叨
又换电脑?哪有钱,打工人穷得很。自用的 MacBook Pro2015 算下来已经快 6 年了,用着倒也还行,但每次听它的风扇呼呼转就心里紧张,清灰,换硅脂,一顿操作下来,不太理想,可能是性能瓶颈了,又困于囊中羞涩,遂入手了一台迷你小主机,几个月 Windows 用下来,始终不顺手,然后就闲置当作了家庭娱乐机,“买前生产力,买后爱奇艺”。
最近,MacBook Pro 的风扇又开始呼呼转了(供暖了),盯着小主机看了看,打起了黑苹果的主意,善用搜索引擎加上不耻下问(咳咳),还算顺利的用上了黑苹果,真香!
头疼的事情又来了,安装软件 ➕ 配置环境,于是就抽空写了个 shell 脚本,调用 homebrew 来自动安装软件。
shell 脚本
构思
homebrew-core 核心库中软件有限,很多软件需要其他 tap,所以需要一个数组用来存储 taps
1
source=()
软件也不少(废话,不然还用得着脚本?),同样需要一个数组:
1
programs=()
既然用了数组,就需要使用循环来取出内容并调用 homebrew:
1
2
3
4
5
6
7
8
9
10
11
12# 获取需要的 tap
for tap in ${source[@]}
do
echo "brew tap $tap" && brew tap $tap
done
# 安装软件
for app in ${programs[@]}
do
echo "brew install $app" && brew install $app
done有些软件在安装过程中需要输入密码,没问题,调用 expect 即可;
基本上就这样了,开始实现吧;
实现
创建 install.sh,按照构思写入基本结构;
tap 部分的代码不用动,直接填入需要的 tap 即可;
安装方面,需要先实现自动输入密码功能,由于需要使用 expect 且解释器不同,所以新建 autoinput.sh 来实现自动填写密码的功能:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
## 预设的电脑密码
set password "你的电脑密码"
## 超时时间,单位:秒
set timeout -1
## 接收传递的应用名称
set program [lindex $argv 0]
## 安装
spawn brew install $program
## 需要密码则输入
expect {
"*assword*:" { send "$password\r"; exp_continue; }
eof
}然后实现 install.sh 中的调用:
1
2
3
4for app in ${programs[@]}
do
./autoinput.sh $app
done填入 tap 和软件,测试一下,完活儿了;
优化
加上注释,空行,软件列表等内容,一共 100 来行的代码居然分成两个文件,合并;
合并的话只需要修改调用 expect 的代码即可,也就是安装软件部分,其他不动:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25for app in ${programs[@]}
do
## 嵌入 expect 自动输入密码
# 声明按照 expect 解析下面的脚本,遇到 EOF 则停止
/usr/bin/expect <<-EOF
## 预设的电脑密码
set password "你的电脑密码"
## 超时时间,单位:秒,-1 表示永不过期
set timeout -1
## 安装应用
spawn brew install $app
## 需要密码则输入
expect {
"*assword*:"
{ send "$password\r"; exp_continue; }
eof
}
# 对应 /usr/bin/expect <<-EOF
EOF
done完整代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
## 电脑需要有 expect 命令,请使用下面命令自查:👇
# whereis expect
# 算了,还是加上安装 expect 吧,反正已安装会自动跳过(辛苦 brew 了)
echo "brew install expect" && brew install expect
## 使用的 tap
# 按需写入,以下是我使用的 tap
source=(
# 你使用的 tap 请写在这里
# 以下内容可以删除
homebrew/cask
homebrew/cask-fonts # font-fira-code
homebrew/cask-drivers # logitech-options
homebrew/cask-versions # clashx-pro
adoptopenjdk/openjdk # adoptopenjdk
bigwig-club/brew # upic
# 删除截止
)
# 获取需要的 tap
for tap in ${source[@]}
do
echo "brew tap $tap" && brew tap $tap
done
## 需要安装的软件列表
programs=(
# 你需要的软件请写在这里
)
## 遍历软件列表并安装应用
# 某些程序在安装时需要输入电脑密码
for app in ${programs[@]}
do
## 嵌入 expect 自动输入密码
# 声明按照 expect 解析下面的脚本,遇到 EOF 则停止
/usr/bin/expect <<-EOF
## 预设的电脑密码
set password "你的电脑密码"
## 超时时间,单位:秒,-1 表示永不过期
set timeout -1
## 安装应用
# 说明:
# brew install xxx 是用来安装命令行应用的
# 安装图形化应用对应的命令是:brew install --cask xxx
# 所以遇到既有命令行也有图形化的应用时,需要说明安装应用的来源
# 如:brew install homebrew/cask/wireshark
spawn brew install $app
## 调试命令:显示 expect 执行的详细信息
# exp_internal 1
## 需要密码则输入
# 匹配"spawn brew install $app"的返回结果
# 如果以'Password:'或'password:'结尾则输入用户密码
expect {
# 模糊匹配,也可以使用 expect -re
"\[P\|p\]assword:$"
# $ 符号需要转义
# 发送密码后需要继续安装
{ send "\$password\r"; exp_continue; }
# expect 无需等待
expect eof
}
# 对应 /usr/bin/expect <<-EOF
# 命令段结束
EOF
done
食用
首先确定自己的电脑有 expect,没有就已添加自动安装 expect;brew install expect
将使用的 tap 写入
source=()
的括号内,举个 🌰:1
2
3
4
5source=(
tap1
tap2 tap3 tap4
)数组元素之间用空白字符分隔,如:空格 / 制表符等等;
将使用的软件名写入
programs=()
的括号内(还是数组,So…):1
2
3
4
5programs=(
qq
qqmusic
qqlive tencent-metting tencent-lemon
)是的,你没看错,shell 中的数组确实是用圆括号
()
表示的,而函数的定义又很常见;软件名必须是 homebrew 中的名称,而不是软件自身的名称,举 🌰:
软件名 homebrew 中的名字 爱奇艺 qiyimedia 阿里云盘 adrive 微信 WeChat … … 有些软件的名字确实很奇怪,无法用自身的软件名去推测,而有些则很友好;
不知道的先用
brew search xxx
搜索一下;macOS 系统版本众多,自 10.15 后软件必须是 64 位,所以有些软件会装不上而出错,很正常;
如:爱奇艺,要求系统必须是 10.15 及以上;
善用搜索引擎;
打完,收工!