-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathphp-ext.sh
395 lines (305 loc) · 10.6 KB
/
php-ext.sh
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
#!/usr/bin/env bash
# sudo rm -rf /etc/apt/sources.list.d/ /var/lib/apt/lists/partial/ && apt update
# set -e
# 安装函数
function install_so(){
{
local tag_dir=''
if ext_config_value_exists $EXT_DEPEND; then
# 等待apt
apt_get_fifo
fi
processes_get_fifo
# 检测依赖扩展
if [[ $install_json_bool > 0 ]];then
check_not_installed "$EXT_SORT"
fi
echo -e "\e[1;1m ==========================${EXT_NAME}开始===================== \e[0m" 1>&2
if [[ -d $EXT_TGZ_DIR ]]; then
tag_dir=$EXT_TGZ_DIR
elif ext_config_value_exists $EXT_URL; then
tag_dir=$temp_dir/$EXT_NAME
tar_file_path=${tag_dir}/${EXT_NAME}'.tgz'
mkdir -p $tag_dir
# 定义下载回来默认文件名
curl_s "$EXT_URL" "${tar_file_path}"
untar $EXT_URL_TYPE ${tar_file_path} $tag_dir
if [[ $install_json_bool > 0 ]];then
# 删除压缩包
rm -rf "${tag_dir}.tgz"
fi
fi
ext_no_make=0
if ext_config_value_exists $EXT_EVAL; then
# 可通过ext_no_make跳过make阶段
eval $EXT_EVAL
fi
if [[ $ext_no_make < 1 ]]; then
cd $tag_dir
# 进入编译目录,如果没有找到会跑到用户目录去
cd `find ./ \( -iname 'config.m4' -o -iname 'config0.m4' \) -exec dirname {} \;`
# config0.m4改为config.m4
if [[ -f config0.m4 ]]; then
mv config0.m4 config.m4
fi
phpize
./configure $EXT_ARG
make && make install
# 删除网络包,install.json安装时才删除
if [[ (! -d $EXT_TGZ_DIR) && $install_json_bool > 0 ]]; then
rm -fr $tag_dir
else
echo '==============================='$tag_dir'============================' 1>&2
fi
fi
processes_write_fifo
} 1> ${log_fd}
# }
# 生成的so文件复制到php.ini指定的目录下
# cp $(php-config --extension-dir)/* $(php -r 'echo ini_get("extension_dir");')
echo -e "\e[1;33m ==========================${EXT_NAME}完成===================== \e[0m"
echo "$EXT_NAME" >> $installed_path
}
# 主方法
php_ext_main(){
echo -e "\e[30;46m ==========================开始安装PHP扩展===================== \e[0m"
# 保持目录
cd $root_dir;
config_path=$root_dir/config.json
install_json_path=$root_dir/install.json
# docker的共享目录无法执行编译操作和fifo
temp_dir=/tmp/php-ext/temp
fifo_tmp_dir='/tmp/php-ext/docker_fifo'
fifo_path=$fifo_tmp_dir/fifo_apt_update
installed_path=$fifo_tmp_dir/file_installed
fifo_lock='ext_apt_update_lock'
# 同步安装数量,使用环境变量
processes_num=${PHP_PROCESSES_NUM:-15}
processes_path=$fifo_tmp_dir/fifo_processes
install_json_bool=1 # 是否通过install.json安装,默认是,否为通过指定扩展安装
mkdir -p ${temp_dir} ${fifo_tmp_dir}
touch $installed_path
echo '' > $installed_path; # 清空
# 判断文件是否存在
if [[ -f ${config_path} ]]; then
# config.json内容
# @todo 待优化为(?<!:),不支持url中包含#的,同时处理/usr/local/php,使用环境变量
config_json_text=`grep -v -E "#|([^:]//)|(^//)" ${config_path} | sed "s#\/usr\/local\/php\/#${PHP_CONFIGURE_DIR}\/#g"`
configNum=$(echo ${config_json_text} | jq '.|length')
if [[ $1 ]]; then
install_json_bool=0
install_json_text=$1
elif [[ -f ${install_json_path} ]]; then
# install.json内容
install_json_text=`grep -v -E "#|//" ${install_json_path}`
fi
# 在docker的数据卷中无法mkfifo
trap "apt_end_fifo ${fifo_path};processes_end_fifo ${processes_path};exit;" 2
mkfifo ${fifo_path}
apt_exec_fifo ${fifo_path}
apt_write_fifo $fifo_lock
# 并发控制
mkfifo ${processes_path}
processes_exec_fifo ${processes_path}
for (( i = 0; i < $processes_num; i++ )); do
processes_write_fifo
done
install_ext_depend
# 循环安装
for (( i = 0; i < $configNum; i++ )); do
# 保持目录
cd $root_dir;
#判断是否安装
EXT_INSTALL=$(echo ${config_json_text} | jq ".[$i].EXT_INSTALL"|sed 's/\"//g');
# 目录名,扩展名
EXT_NAME=$(echo ${config_json_text} | jq -r ".[$i].EXT_NAME");
if [[ ! -f ${install_json_path} && $EXT_INSTALL != 1 ]] || \
# 已安装
[[ $(grep "${EXT_NAME}" $installed_path | wc -l) < 0 ]] || \
[[ -f ${install_json_path} && ! ( \
$(echo ${install_json_text} | jq -r ".[0]") == 'all' || \
$(echo ${install_json_text} | jq -r ".[]" | grep -e "^${EXT_NAME}$") \
) ]]; then
# 不安装
continue;
fi
# 下载文件地址
EXT_URL=$(echo ${config_json_text} | jq -r ".[$i].EXT_URL");
# 安装顺序
EXT_SORT=$(echo ${config_json_text} | jq -r ".[$i][\"EXT_SORT\"]");
# 编译参数
EXT_ARG=$(echo ${config_json_text} | jq -r ".[$i].EXT_ARG" | sed 's/^null$//i');
# 已有的源码路径,用于安装如mysqli这类在php安装包里自带有源码扩展的扩展
EXT_TGZ_DIR=$(echo ${config_json_text} | jq -r ".[$i].EXT_TGZ_DIR");
# 扩展依赖(存在即安装),通过apt-get安装,可用apt-cache search来搜索对应名称
EXT_DEPEND=$(echo $(echo ${config_json_text} | jq -r ".[$i].EXT_DEPEND"));
# 执行自定义命令
EXT_EVAL=$(echo $(echo ${config_json_text} | jq -r ".[$i].EXT_EVAL"));
# 下载文件后解压命令类型
EXT_URL_TYPE=$(echo $(echo ${config_json_text} | jq -r ".[$i].EXT_URL_TYPE"));
install_so&
done
# 等待所有后台任务执行完毕
wait
else
install_so
fi
}
# 一次安装所有需要的扩展
install_ext_depend(){
local num=$(echo ${config_json_text} | jq '.|length')
local ext_depend=''
local temp_ext_depend=''
local ext_depend_num=0
# [[ -f ${install_json_path} && ! ($(echo ${install_json_text} | jq -r ".[0]") == 'all' ||
# $(echo ${install_json_text} | jq -r ".[]" | grep -e "^${EXT_NAME}$")) ]]
if [[ -f ${install_json_path} && $(echo ${install_json_text} | jq -r ".[0]") == 'all' ]]; then
# 安装所有
ext_depend=`echo ${config_json_text} | jq -r '.[].EXT_DEPEND' | tr -s "\n" " "`
ext_depend_num=`echo ${config_json_text} | jq -r '.[].EXT_DEPEND' | grep -v -e "^\s*$" | wc -l`
else
for (( i = 0; i < $num; i++ )); do
temp_ext_depend=$(echo $(echo ${config_json_text} | jq -r ".[$i].EXT_DEPEND"))
# 目录名,扩展名
temp_ext_name=$(echo ${config_json_text} | jq -r ".[$i].EXT_NAME");
if [[ ! -f ${install_json_path} && $(echo ${config_json_text} | jq -r ".[$i].EXT_INSTALL") != 1 ]] || ([[ -f ${install_json_path} && $(echo ${install_json_text} | jq -r ".[]" | grep -e "^${temp_ext_name}$") ]] && ext_config_value_exists $temp_ext_depend ); then
ext_depend+=' '${temp_ext_depend}
((ext_depend_num++))
fi
done
fi
# 去除第一个空格
ext_depend=`echo $ext_depend | sed 's/^\s+//g'`
if ext_config_value_exists $ext_depend; then
{
apt_get_fifo
# if [[ $fifo_val == $fifo_lock ]]; then
# fi
echo -e "\e[1;1m ==========================apt开始===================== \e[0m" 1>&2
apt update
# 不支持并发执行
export DEBIAN_FRONTEND=noninteractive
apt install -y --no-install-recommends $ext_depend
echo -e "\e[1;33m ==========================apt完成===================== \e[0m" 1>&2
# @todo 可改用信号
for (( i = 0; i < $ext_depend_num; i++ )); do
apt_write_fifo
done
} 1> ${log_fd} &
# } &
# 等待查找
# sleep 2
fi
}
# 检查是否存在值
ext_config_value_exists(){
if [[ $1 > 0 && $1 != null ]]; then
# 成功
return 0
else
return 1
fi
}
# $1 写入的内容
apt_write_fifo(){
echo "$1">&33
}
apt_get_fifo(){
local row=''
read -u33 row
echo $row
}
# $1 fifo地址
apt_exec_fifo(){
exec 33<>$1
rm -fr $1
}
apt_end_fifo(){
rm -fr $1;
exec 33>&-;
exec 33<&-;
}
processes_end_fifo(){
rm -fr $1;
exec 32>&-;
exec 32<&-;
}
# $1 写入的内容
processes_write_fifo(){
echo "$1" >&32
}
processes_get_fifo(){
local row=''
read -u32 row
echo $row
}
# $1 fifo地址
processes_exec_fifo(){
exec 32<>$1
rm -fr $1
}
# 控制curl是否显示进度条
curl_s(){
# 多任务需要下载时有可能失败
if [[ $log_fd = '/dev/null' ]]; then
curl -L --retry 3 -fs "$1" -o "$2"
else
curl -L --retry 3 -f "$1" -o "$2"
fi
}
# 多种解压方式
untar(){
if [[ $1 == 'zip' ]]; then
unzip -o $2 -d $3
else
tar -zxf "$2" -C $3
fi
}
function check_not_installed(){
local val;
if ! ext_config_value_exists "$1"; then
# 可以安装
return 1
fi
local check_arr=$(echo $1|jq -r ".[]")
for val in $check_arr; do
if [[ `grep "${val}" ${installed_path} | wc -l` < 1 ]]; then
cat $installed_path 1>&2;
echo $val 1>&2;
processes_reset_fifo "$EXT_NAME"
check_not_installed "$1"
return;
fi
echo 'success install'; 1>&2;
echo $val 1>&2;
done
return 1
}
function processes_reset_fifo(){
processes_write_fifo
echo '重新构建'$1 1>&2;
sleep 1
processes_get_fifo
}
# 执行
start_time=`date "+%s"`
root_dir=$(cd $(dirname $(readlink -f $0));pwd)
log_fd='/dev/null'
# 支持 ./php-ext.sh curl
if [[ $# > 0 ]]; then
# 直接调用时显示输出
log_fd='/proc/self/fd/1'
opt_json_text=''
for i in $*; do
opt_json_text+='"'${i}'",'
done
opt_json_text='['${opt_json_text:0:-1}']'
# 传参安装
php_ext_main $opt_json_text
else
# 用install安装
php_ext_main;
fi
let end_time=`date "+%s"`-start_time
echo -e "\e[30;46m ---------------------------------Time : "${end_time}"--------------------------------------- \e[0m"
echo