Road to growth of rookie

Meaningful life is called life

0%

MAC 环境下构建 PHP 自动化环境工具 V2.0

前段时间手撸一个 PHP 的本地自动化环境脚本, 跟朋友分享了一波之后收到了绝大多数的好评. 但是在实际使用的过程中还是有不少的问题, 因为刚入职了新公司也没有时间去升级, 今天刚好有空抽出来两个小时升级一下.

实际使用中遇到的问题:

首先是对 Mac 系统产生依赖, 不能直接移植到 Linux 上; 因为我一直使用的都是 Mac, 它本身自带了 Apache, 当时为了节省时间直接使用 Apache 作为代理服务器, 但是 Linux 本身不会默认安装, 所以这个需要优化. 这个优化上次也提过, 就是通过 docker 拉起一个 nginx 的代理镜像, 通过代理镜像把流量转发到业务容器上.

第二就是 域名root目录 等都是固定不可配置的, 但是我在实际开发过程中还有 Yii 的项目, 需要修改 root 指向地址. 之前都是拉起业务容器后, 进入到容器内手动去修改, 很不方便, 这个也需要优化, 改成通过参数的方式传递给脚本.

项目地址: https://gogs.ijunj.com/common/php-link-tool

工具在 macubuntu 系统下, 运行正常, 要不是我实在搞不懂 windows, 我真想也搞上, 这样才是一个完整的脚本嘛

修改初始化脚本

考虑到 Linux 多用户的问题, 把代理镜像的配置文件目录分配到了 /etc 目录下, 建一个 php-link-tool 用户组. 将配置文件目录分配到 php-link-tool 用户组下.

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
#!/bin/sh

if [ "$(docker images -q base/php-openresty:latest)" = "" ]; then
docker build -t base/php-openresty:latest --no-cache .
fi

uname=$(uname)
case $uname in
"Darwin") config_files_path="$HOME/.php-link-tool/conf.d" ;;
"Linux") config_files_path="/etc/php-link-tool/conf.d" ;;
*) echo "Unknown system: $uname" && exit 1 ;;
esac

if [ ! -d "$config_files_path" ]; then
if [ "$uname" = "Linux" ]; then
sudo mkdir -p "$config_files_path"
sudo cp openresty/default.conf.back "$config_files_path"
else
mkdir -p "$config_files_path" && cp openresty/default.conf.back "$config_files_path"
fi

fi

if [ "$uname" = "Linux" ]; then
groupExists=$(grep -E '^php-link-tool' /etc/group)

set -o errexit;

if [ "$groupExists" = "" ]; then
sudo groupadd php-link-tool \
&& sudo chgrp php-link-tool "$config_files_path" \
&& sudo chmod g+w "$config_files_path" \
&& sudo usermod -a -G php-link-tool "$USER"
fi
fi

docker run --name="php-proxy-openresty" \
--restart=always -p 80:80 \
-v "$config_files_path":/etc/nginx/conf.d \
-d openresty/openresty:1.17.8.2-alpine

docker exec php-proxy-openresty mkdir -p /var/log/nginx

sudo cp php-link-tool-v2.sh /usr/local/bin/php-link-tool
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
#!/bin/sh

set -o errexit

Listening() {
listenNum=$(sudo lsof -i :$1 | grep -v "PID" | awk "{print $2}")
if [ "$listenNum" != "" ]; then
return 1
fi

return 0
}

helpTips="Usage: php-link-tool [options] [args]
php-link-tool link [path] [container_name] [container_path] Link to a new project
php-link-tool unlink [name] Unlink a project"

if [ $# -lt 1 ]; then echo "$helpTips" && exit 1; fi
if [ "$1" != "link" ] && [ "$1" != "unlink" ]; then echo "$helpTips" && exit 1; fi

uname=$(uname)

if [ "$(docker ps -q -f name="php-proxy-openresty")" != "" ]; then
vhosts=$(docker inspect php-proxy-openresty | grep Mounts -A 20 | grep "Source" | sed 's/[ ",]*//g' | cut -c 8-)
else
echo "Run install.sh to initialize the environment" && exit 1
fi

case $uname in
"Darwin") sedCommand="sed -i '' -e" ;;
"Linux") sedCommand="sed -i" ;;
*) echo "Unknown system: $uname" && exit 1 ;;
esac

case $1 in
"link")
if [ "$(docker images -q base/php-openresty:latest)" = "" ]; then
echo "Run install.sh to initialize the environment" && exit 1
fi

if [ $# -gt 1 ]; then path=$2; else path=$(pwd); fi
if [ $# -gt 2 ]; then containerName=$3; else containerName=${path##*/}; fi
if [ $# -gt 3 ]; then containerPath=$4; else containerPath="/www/public"; fi

if [ "$(docker ps -aq -f name="$containerName")" != "" ]; then
if [ "$(docker inspect --format '{{.State.Running}}' "$containerName")" = "false" ]; then
docker rm "$containerName"
else
echo "The $containerName project is already running, To disable this function, run the php-link-tool unlink <name> command" && exit 1
fi
fi

# port=$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()')
port=0
while [ $port = 0 ]; do
randomNum=$(od -An -N2 -i /dev/urandom | awk -F ' ' '{print $1}')
port=$((randomNum % 32768 + 32768))
if [ "$(Listening "$port")" = 1 ]; then
port=0
fi
done

docker run --name="$containerName" \
--restart=always -p "$port":80 \
-v "$path":/www \
-e SOURCE_PATH="$containerPath" \
-d base/php-openresty:latest
echo "127.0.0.1 $containerName.local" | sudo tee -a /etc/hosts >/dev/null
cp "$vhosts/default.conf.back" "$vhosts/$containerName.local.conf"

if [ "$uname" = "Darwin" ]; then
externalIp="docker.for.mac.host.internal"
elif [ "$uname" = "Linux" ]; then
externalIp=$(ifconfig docker0 | grep inet | grep -v inet6 | awk '{match($0,/[0-9\.]+/);print substr($0,RSTART,RLENGTH)}')
else
echo "Unknown system: $uname" && exit 1
fi

eval "$sedCommand" "s/localhost/$containerName.local/g" "$vhosts/$containerName.local.conf"
eval "$sedCommand" "s/127.0.0.1:80/$externalIp:$port/g" "$vhosts/$containerName.local.conf"

;;

"unlink")
if [ $# -gt 1 ]; then containerName=$2; else
path=$(pwd)
containerName=${path##*/}
fi

if [ "$(docker ps -aq -f name="$containerName")" != "" ]; then
docker stop "$containerName" && docker rm "$containerName"
eval "sudo $sedCommand" "s/^127.*$containerName.local$//g" /etc/hosts
vhostFile="$vhosts/$containerName.local.conf"
if [ -f "$vhostFile" ]; then sudo rm -f "$vhostFile"; fi
fi

;;
esac

docker exec php-proxy-openresty openresty -s reload
添加容器运行脚本 start.sh

上述问题中有一个项目中可能存在多个入口, 那 Nginxroot 目录就是变量, 找了一圈没有找到什么好的办法. 只能在拉起容器时给一个环境变了 $SOURCE_PATH. 容器运行脚本替换配置文件内 root 目录的指向

1
2
3
4
5
6
#!/bin/sh

code_source_path=$(echo "$SOURCE_PATH" | sed -e 's/\//\\\//g')
sed -i "s/\/www\/public/$code_source_path/g" /etc/nginx/conf.d/default.conf

/usr/bin/supervisord -n -c /etc/supervisord.conf