89293f87 by 周伟奇

first commit

0 parents
1 ## 1.目录结构
2 ```
3 .
4 ├── bin
5 │   ├── conf.sh
6 │   ├── control.sh 运维操作脚本
7 │   ├── docker.sh
8 │   └── utils.sh
9 ├── configs
10 │   └── settings.sh 配置文件
11 │   └── license 授权文件目录
12 ├── logs 日志文件目录
13 └── repo
14 ├── images docker镜像文件目录
15 ├── models
16 └── python
17 ```
18 ---
19
20 ## 2.服务部署
21
22 ### 2.1 授权管理
23 - 获取服务器信息,发给授权人员生成授权文件(已有授权文件忽略此步骤)
24 ```shell
25 bin/control.sh systeminfo
26 ```
27 - 授权文件更新
28 ```shell
29 bin/control.sh update_license /path_to/xxx.secret
30 ```
31
32 ### 2.2 配置文件
33 - 编辑`configs/settings.sh`
34 ```
35 # 日志目录
36 LOG_BASE_DIR=${BASE_DIR}/logs
37
38 # 端口
39 BACKEND_PORT=80
40 # TODO 此端口随机,不需要配置
41 TRITON_HTTP_PORT=8000
42 TRITON_GRPC_PORT=8001
43 TRITON_METRICS_PORT=8002
44
45 # sanic-worker TODO 可配置
46 BACKEND_SANIC_WORKER_NUM=4
47
48 # GPU/CPU
49 # 使用CPU: TRITON_GPUS=
50 # 使用GPU0/GPU1: TRITON_GPUS=0,1
51 TRITON_GPUS=0
52 ```
53
54 ### 2.3 启动
55 ```shell
56 bin/control.sh start all
57 ```
58
59 ### 2.4 停止
60 ```shell
61 bin/control.sh stop all
62 ```
63
64 ### 2.5 重启
65 - 重启后端服务,适用于只更新了授权文件
66 ```shell
67 bin/control.sh restart backend
68 ```
69 - 重启所有,适用于更新了repo文件夹
70 ```shell
71 bin/control.sh restart all
72 ```
73
74 ### 2.6 日志查看
75 ```shell
76 bin/control.sh logs triton
77 bin/control.sh logs backend
78 ```
79
80 ## TODO
81 - 授权部分
82 - backend logs
83 - backend sanic worker num可配置
84 - 随机选择triton端口,该配置项无意义
85 - ASGI & supervisor ?
86 - async ?
...\ No newline at end of file ...\ No newline at end of file
1 #!/bin/bash
2 set -euo pipefail
3
4 # shellcheck is a shell lint
5 # shellcheck disable=SC1091
6 # shellcheck disable=SC1090
7 source "${_BIN_DIR}/utils.sh"
8
9 # 目录相关
10 # 配置文件目录
11 CONFIG_DIR=${BASE_DIR}/configs
12 # 授权文件目录
13 LICENSE_DIR=${CONFIG_DIR}/license
14 REPO_DIR=${BASE_DIR}/repo
15 # docker镜像目录
16 DOCKER_IMAGE_DIR=${REPO_DIR}/images
17 # 模型与代码相关目录
18 BACKEND_PYTHON_DIR=${REPO_DIR}/python
19 TRITON_MODEL_DIR=${REPO_DIR}/models
20
21 # docker相关
22 # triton相关
23 TRITON_CONTAINER_NAME=tritonserver
24 TRITON_IMAGE_NAME=tritonserver
25 TRITON_IMAGE_TAG=1.0
26 TRITON_IMAGE=${TRITON_IMAGE_NAME}:${TRITON_IMAGE_TAG}
27 TRITON_IMAGE_SAVE_NAME=tritonserver-tf2-pt.tar
28 TRITON_IMAGE_SAVE_PATH=${DOCKER_IMAGE_DIR}/${TRITON_IMAGE_SAVE_NAME}
29 # 工程相关
30 BACKEND_CONTAINER_NAME=situ-ocr
31 BACKEND_IMAGE_NAME=situ-ocr
32 BACKEND_IMAGE_TAG=1.0
33 BACKEND_IMAGE=${BACKEND_IMAGE_NAME}:${BACKEND_IMAGE_TAG}
34 BACKEND_IMAGE_SAVE_NAME=situ-ocr.tar
35 BACKEND_IMAGE_SAVE_PATH=${DOCKER_IMAGE_DIR}/${BACKEND_IMAGE_SAVE_NAME}
36
37 # 加载配置数据
38 _config_file_path="${CONFIG_DIR}/settings.sh"
39
40 if [ -f "${_config_file_path}" ]; then
41 # shellcheck disable=SC1091
42 # shellcheck disable=SC1090
43 source "${_config_file_path}"
44 else
45 _notify ERROR "config file <${_config_file_path}> does not exist"
46 exit 1
47 fi
48
49 # 这些配置依赖configs/settings.sh, 所以需要放在source之后
50 # TRITON容器启动参数相关
51 # -env
52 TRITON_CONTAINER_ENVS=()
53 TRITON_ENVS_OPTION=""
54 if (( ${#TRITON_CONTAINER_ENVS[@]} > 0 )); then
55 checkEnvsOption ${TRITON_CONTAINER_ENVS[@]}
56 TRITON_ENVS_OPTION="$(getOption "-env" ${TRITON_CONTAINER_ENVS[@]})"
57 fi
58 # -v
59 TRITON_CONTAINER_MODEL_DIR=/models
60 TRITON_CONTAINER_VOLUMES=(
61 "${TRITON_MODEL_DIR}:${TRITON_CONTAINER_MODEL_DIR}"
62 )
63 TRITON_VOLUMES_OPTION=""
64 if (( ${#TRITON_CONTAINER_VOLUMES[@]} > 0 )); then
65 checkVolumesOption ${TRITON_CONTAINER_VOLUMES[@]}
66 TRITON_VOLUMES_OPTION="$(getOption "-v" ${TRITON_CONTAINER_VOLUMES[@]})"
67 fi
68 # -p
69 TRITON_CONTAINER_PORTS=(
70 "${TRITON_HTTP_PORT}:8000"
71 "${TRITON_GRPC_PORT}:8001"
72 "${TRITON_METRICS_PORT}:8002"
73 )
74 TRITON_PORTS_OPTION=""
75 if (( ${#TRITON_CONTAINER_PORTS[@]} > 0 )); then
76 checkPortUsedStatus ${TRITON_CONTAINER_PORTS[@]}
77 TRITON_PORTS_OPTION="$(getOption "-p" ${TRITON_CONTAINER_PORTS[@]})"
78 fi
79 # --gpus
80 TRITON_GPUS_OPTION=""
81 if [ $TRITON_GPUS ]; then
82 TRITON_GPUS_OPTION="--gpus \"device=${TRITON_GPUS}\""
83 fi
84 # -env -v -p --gpus --model-repository
85 TRITON_OPTIONS="${TRITON_ENVS_OPTION} ${TRITON_VOLUMES_OPTION} ${TRITON_PORTS_OPTION} ${TRITON_GPUS_OPTION} --model-repository=${TRITON_CONTAINER_MODEL_DIR}"
86
87 # BACKEND容器启动参数相关
88 # -env
89 BACKEND_CONTAINER_ENVS=(
90 "WORKER_NUM=${BACKEND_WORKER_NUM}"
91 )
92 BACKEND_ENVS_OPTION=""
93 if (( ${#BACKEND_CONTAINER_ENVS[@]} > 0 )); then
94 checkEnvsOption ${BACKEND_CONTAINER_ENVS[@]}
95 BACKEND_ENVS_OPTION="$(getOption "-env" ${BACKEND_CONTAINER_ENVS[@]})"
96 fi
97 # -v
98 BACKEND_CONTAINER_VOLUMES=(
99 "${LOG_BASE_DIR}:/logs"
100 )
101 BACKEND_VOLUMES_OPTION=""
102 if (( ${#BACKEND_CONTAINER_VOLUMES[@]} > 0 )); then
103 checkVolumesOption ${BACKEND_CONTAINER_VOLUMES[@]}
104 BACKEND_VOLUMES_OPTION="$(getOption "-v" ${BACKEND_CONTAINER_VOLUMES[@]})"
105 fi
106 # -p
107 BACKEND_CONTAINER_PORTS=(
108 "${BACKEND_PORT}:9002"
109 )
110 BACKEND_PORTS_OPTION=""
111 if (( ${#BACKEND_CONTAINER_PORTS[@]} > 0 )); then
112 checkPortUsedStatus ${BACKEND_CONTAINER_PORTS[@]}
113 BACKEND_PORTS_OPTION="$(getOption "-p" ${BACKEND_CONTAINER_PORTS[@]})"
114 fi
115 # -env -v -p
116 BACKEND_OPTIONS="${BACKEND_ENVS_OPTION} ${BACKEND_VOLUMES_OPTION} ${BACKEND_PORTS_OPTION}"
...\ No newline at end of file ...\ No newline at end of file
1 #/bin/bash
2 set -euo pipefail
3
4 _BIN_DIR=$(dirname "$(readlink -f "$0")")
5 BASE_DIR=$(dirname "${_BIN_DIR}")
6
7 # shellcheck disable=SC1091
8 # shellcheck disable=SC1090
9 source "${_BIN_DIR}/conf.sh"
10 # shellcheck disable=SC1091
11 # shellcheck disable=SC1090
12 source "${_BIN_DIR}/docker.sh"
13
14 function _control_triton(){
15 cat <<END
16
17 triton settings:
18 TRITON_IMAGE: ${TRITON_IMAGE}
19 TRITON_CONTAINER_NAME: ${TRITON_CONTAINER_NAME}
20 TRITON_OPTIONS: ${TRITON_OPTIONS}
21 TRITON_IMAGE_SAVE_PATH: ${TRITON_IMAGE_SAVE_PATH}
22
23 END
24 case "${1:-help}" in
25 start) _docker_func start "${TRITON_IMAGE}" "${TRITON_CONTAINER_NAME}" "${TRITON_OPTIONS}" "${TRITON_IMAGE_SAVE_PATH}" ;;
26 stop) _docker_func stop "${TRITON_CONTAINER_NAME}" ;;
27 restart) _docker_func restart "${TRITON_CONTAINER_NAME}" ;;
28 rm) _docker_func rm "${TRITON_CONTAINER_NAME}" ;;
29 inside) _docker_func inside "${TRITON_CONTAINER_NAME}" ;;
30 top) _docker_func top "${TRITON_CONTAINER_NAME}" ;;
31 dlogs) _docker_func logs "${TRITON_CONTAINER_NAME}" ;;
32 logs) _docker_func logs "${TRITON_CONTAINER_NAME}" ;;
33 is_running) _docker_func is_running "${TRITON_CONTAINER_NAME}" ;;
34 debug) _docker_func debug "${TRITON_IMAGE}" "${TRITON_CONTAINER_NAME}" "${TRITON_OPTIONS}" ;;
35 # 其他
36 *) _echo_help_message ;;
37 esac
38 }
39
40 function _control_backend(){
41 cat <<END
42
43 backend settings:
44 BACKEND_IMAGE: ${BACKEND_IMAGE}
45 BACKEND_CONTAINER_NAME: ${BACKEND_CONTAINER_NAME}
46 BACKEND_OPTIONS: ${BACKEND_OPTIONS}
47 BACKEND_IMAGE_SAVE_PATH: ${BACKEND_IMAGE_SAVE_PATH}
48
49 END
50 case "${1:-help}" in
51 start) _docker_func start "${BACKEND_IMAGE}" "${BACKEND_CONTAINER_NAME}" "${BACKEND_OPTIONS}" "${BACKEND_IMAGE_SAVE_PATH}" ;;
52 stop) _docker_func stop "${BACKEND_CONTAINER_NAME}" ;;
53 restart) _docker_func restart "${BACKEND_CONTAINER_NAME}" ;;
54 rm) _docker_func rm "${BACKEND_CONTAINER_NAME}" ;;
55 inside) _docker_func inside "${BACKEND_CONTAINER_NAME}" ;;
56 top) _docker_func top "${BACKEND_CONTAINER_NAME}" ;;
57 dlogs) _docker_func logs "${BACKEND_CONTAINER_NAME}" ;;
58 is_running) _docker_func is_running "${BACKEND_CONTAINER_NAME}" ;;
59 debug) _docker_func debug "${BACKEND_IMAGE}" "${BACKEND_CONTAINER_NAME}" "${BACKEND_OPTIONS}" ;;
60 # 其他
61 *) _echo_help_message ;;
62 esac
63 }
64
65 function _control_all(){
66 case "${1:-help}" in
67 start) _control_triton start && _control_backend start ;;
68 stop) _control_triton stop && _control_backend stop ;;
69 restart) _control_triton restart && _control_backend restart ;;
70 rm) _control_triton rm && _control_backend rm ;;
71 # 其他
72 *) _echo_help_message ;;
73 esac
74 }
75
76 # 更新授权文件
77 function _updateLincese(){
78 local license_file="$1"
79 if ! [ -e "${license_file}" ];
80 then
81 _notify ERROR "license file <${license_file}> does not exist" ;
82 exit 1
83 fi
84
85 local target_file=${LICENSE_DIR}/$(basename ${license_file})
86 if [ -e "${target_file}" ];
87 then
88 now=$(date +%Y-%m-%d_%H:%M:%S)
89 backup_path="${target_file}__backup_${now}"
90 mv "${target_file}" "${backup_path}"
91 _notify SUCCESS "\"${target_file}\" already exists, mv to ${backup_path}"
92 fi
93
94 cp "${license_file}" "${LICENSE_DIR}"
95 _notify SUCCESS "cp \"${license_file}\" to ${LICENSE_DIR}"
96 }
97
98 function _echo_help_message(){
99 cat <<END
100
101 用法: $(basename "$0") [选项] [参数] ...
102
103 Container(容器):
104 - start triton/backend/all 启动部署用的容器
105 - stop triton/backend/all 停止当前部署的容器
106 - restart triton/backend/all 重启当前部署的容器
107 - rm triton/backend/all 删除当前部署的容器
108 - inside triton/backend 已交互式进入当前部署的容器
109 - is_running triton/backend 判断当前部署的容器是否在运行
110 - top triton/backend 查看当前部署的容器的进程
111 - dlogs triton/backend 查看当前部署的容器的日志
112 - debug triton/backend 创建并以交互式进入debug用的容器
113
114 Tools(工具):
115 - logs triton/backend 查看运行日志
116 - systeminfo 查看系统信息,用于授权
117 - update_license 更新授权文件
118
119 END
120 }
121
122 function _getSystemInfo(){
123 echo "尚未完成"
124 }
125
126 function _server_control() {
127 case "${2:-help}" in
128 triton) _control_triton $1 ;;
129 backend) _control_backend $1 ;;
130 all) _control_all $1 ;;
131 # 其他
132 *) _echo_help_message ;;
133 esac
134 }
135
136 case "${1:-help}" in
137 systeminfo) _getSystemInfo ;;
138 update_license) _updateLincese $2 ;;
139 * ) _server_control $@ ;;
140 esac
1 #!/bin/bash
2
3 function _docker_run(){
4 local run_type=$1
5 local image=$2
6 local container_name=$3
7 local input_options=$4
8 local all_options
9
10 if [ ${run_type} = "up" ]; then
11 # 启动部署用的container
12 all_options = "-d --net=bridge ${input_options} --name ${container_name} ${image}"
13 else
14 # 创建debug用的container
15 all_options = "-it --rm --net=bridge ${input_options} --entrypoint=/bin/bash ${image}"
16 fi
17
18 _notify INFO "run image ${image} with options: ${all_options}"
19 docker run ${all_options}
20 _notify SUCCESS "run image ${image} with options: ${all_options}"
21 }
22
23
24 function _load(){
25 local load_file=$1
26 if ! [ -e "${load_file}" ];
27 then
28 _notify ERROR "file <${load_file}> to be loaded does not exist" ;
29 exit 1
30 fi
31
32 _notify INFO "loading docker image from file <${load_file}>"
33 docker load -i ${load_file}
34 _notify SUCCESS "loaded docker image from file <${load_file}>"
35 }
36
37
38 # 判断镜像是否存在
39 function _is_image_exists(){
40 local image_name=$1
41 local image_id
42 image_id=$(docker image ls -a -q ${image_name})
43 if [ ! "${image_id}" ]; then
44 echo "false"
45 else
46 echo "true"
47 fi
48 }
49
50
51 function _start(){
52 echo $@
53 local image_name=$1
54 local container_name=$2
55 local input_options=$3
56 local load_file=$4
57 local container_id
58 container_id=$(docker ps -a -q -f name="^/${container_name}$")
59 if [ ! "${container_id}" ]; then
60 if [ "$(_is_image_exists "${image_name}")" != "true" ]; then
61 _notify WARNING "image <${image_name}> does not exist"
62 _load ${load_file}
63 fi
64 _docker_run "up" ${image_name} ${container_name} ${input_options}
65 else
66 docker start "${container_id=}"
67 fi
68 }
69
70
71 # 判断容器是否存在
72 function _is_container_exists(){
73 local container_name=$1
74 local container_id
75 container_id=$(docker ps -a -q -f name="^/${container_name}$")
76 if [ ! "${container_id}" ]; then
77 echo "false"
78 else
79 echo "true"
80 fi
81 }
82
83
84 # 检测容器是否运行
85 function _is_container_running(){
86 if [ "$(_is_container_exists "$1")" != "true" ]; then
87 _notify ERROR "container <$1> does not exist"
88 exit 1
89 fi
90 docker inspect -f '{{.State.Running}}' "$1"
91 }
92
93 # 调用
94 function _docker_func(){
95 case "$1" in
96 start) shift 1 && _start "$@" ;;
97 stop) shift 1 && docker stop "$@" ;;
98 restart) shift 1 && docker restart "$@" ;;
99 rm) shift 1 && docker rm "$@" ;;
100 inside) shift 1 && docker exec -it "$@" /bin/bash ;;
101 top) shift 1 && docker top "$@" ;;
102 logs) shift 1 && docker logs "$@";;
103 is_running) shift 1 && _is_container_running "$@" ;;
104 debug) shift 1 && _docker_run "debug" "$@";;
105 esac
106 }
...\ No newline at end of file ...\ No newline at end of file
1 #!/bin/bash
2 set -euo pipefail
3
4 ####################################
5 # 常用工具
6 ####################################
7
8 # 输出带有颜色的文本
9 function _notify(){
10 local _type=$1
11 local _msg=$2
12 local _GREEN
13 _GREEN=$(tput setaf 2)
14 local _YELLOW
15 _YELLOW=$(tput setaf 190)
16 local _RED
17 _RED=$(tput setaf 1)
18 local _NORMAL
19 _NORMAL=$(tput sgr0)
20 local _color_flag
21
22 case ${_type} in
23 INFO) _color_flag=${_NORMAL} ;;
24 SUCCESS) _color_flag=${_GREEN} ;;
25 WARNING) _color_flag=${_YELLOW} ;;
26 ERROR) _color_flag=${_RED} ;;
27 *)
28 _color_flag=${_RED}
29 echo "${_color_flag} invalid type: ${_type}${_NORMAL}"
30 return 1;;
31 esac
32
33 printf -- "${_color_flag}${_type}\t${_NORMAL}$(date +"%F %T")\t${_msg}\\n"
34 }
35
36 # 检查端口占用情况
37 function checkPortUsedStatus() {
38 if (( $# > 0 )); then
39 for option in $@ ;
40 do
41 local section_num
42 section_num=$(echo "${option}" | awk -F ':' '{print NF}')
43 if [ "${section_num}" -ne "2" ] ; then
44 _notify ERROR "invalid port config <${option}>"
45 exit 1
46 fi
47 # 检查端口是否为数字
48 local port
49 port=$(echo "${option}"| awk -F ':' '{print $1}')
50 if [ -n "$(echo ${port} | sed 's/[0-9]//g')" ] ; then
51 _notify ERROR "invalid port config <${option}>"
52 exit 1
53 fi
54 # 检查端口占用情况
55 if lsof -i tcp:${port} | grep -q LISTEN; then
56 _notify ERROR "${port}端口被占用,请手动关闭"
57 lsof -i tcp:${port} | grep LISTEN
58 exit 1
59 fi
60 done
61 fi
62 }
63
64 # 获取容器的env配置选项
65 # 判断envs配置是否合法, 方法为判断"="的个数
66 function checkEnvsOption() {
67 if (( $# > 0 )); then
68 for _env in $@ ;
69 do
70 if [ "$(echo "${_env}" | awk -F '=' '{print NF}' )" -ne "2" ]; then
71 _notify ERROR "invalid env config <${_env}>"
72 exit 1
73 fi
74 done
75 fi
76 }
77
78 # 获取容器的volume配置选项
79 # 判断volumes配置是否合法
80 # * local_abs_path:remote_abs_path:flag
81 # * local_abs_path:remote_abs_path
82 # 目前简单判断,仅判断是否包含":",以及local_abs_path是否存在
83 function checkVolumesOption() {
84 if (( $# > 0 )); then
85 for volume in $@ ;
86 do
87 local section_num
88 section_num=$(echo "${volume}" | awk -F ':' '{print NF}')
89 if [ "${section_num}" -ne "2" ] && [ "${section_num}" -ne "3" ]; then
90 _notify ERROR "invalid volume config <${volume}>"
91 exit 1
92 fi
93 # 判断本地文件夹是否存在
94 local local_dir
95 local_dir=$(echo "${volume}"| awk -F ':' '{print $1}')
96 if ! [ -e "${local_dir}" ];
97 then
98 _notify ERROR "dir <${local_dir}> to be mounted does not exist" ;
99 exit 1
100 fi
101 done
102 fi
103 }
104
105 function getOption() {
106 local _type=$1
107 local output_option
108 output_option=""
109 shift 1
110 if (( $# > 0 )); then
111 for _option in $@ ;
112 do
113 output_option="${output_option}${_type} ${_option} "
114 done
115 fi
116 echo ${output_option}
117 }
118
119 # 如果文件夹存在就将其备份
120 # 备份方法为将文件夹重命名为 "原始文件夹名称+当前时间+4未随机字符串"
121 # 使用随机字符串是为了避免同一时间多次跑脚本导致文件夹重复
122 # backup_dir_if_exists $some_dir
123 function backup_dir_if_exists(){
124 if [ -d "$1" ]
125 then
126 now=$(date +%Y-%m-%d_%H:%M:%S)
127 random_string=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c4)
128 backup_dirname="$1__backup_${now}_${random_string}"
129 mv "$1" "${backup_dirname}"
130 _notify SUCCESS "\"$1\" already exists, mv to ${backup_dirname}"
131 fi
132 }
1 #!/bin/bash
2 set -euo pipefail
3
4 # 日志目录
5 LOG_BASE_DIR=${BASE_DIR}/logs
6
7 # 端口
8 BACKEND_PORT=80
9 TRITON_HTTP_PORT=8000
10 TRITON_GRPC_PORT=8001
11 TRITON_METRICS_PORT=8002
12
13 # sanic-worker
14 BACKEND_WORKER_NUM=4
15
16 # GPU/CPU
17 # 使用CPU: TRITON_GPUS=
18 # 使用GPU0/GPU1: TRITON_GPUS=0,1
19 TRITON_GPUS=0
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!