install_deps.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #!/usr/bin/env bash
  2. # =============================================================================
  3. # FranklinWH Toolbox - 依赖检测与安装脚本(Ubuntu)
  4. # =============================================================================
  5. # 作用:检测并(按需)安装本项目所需的数据库引擎与运行时组件:
  6. # - PostgreSQL 14+
  7. # - MongoDB 8.0
  8. # - Redis 7.x
  9. # - MinIO(对象存储)+ mc(MinIO Client)
  10. # - Docker + Docker Compose 插件(Casdoor 需要)
  11. # - Go 1.26 / Node 22 + pnpm(仅“构建”时需要,可选)
  12. # - uv(Python 包/工具管理器,uvx 拉起 MCP server 等,可选)
  13. #
  14. # 特点:
  15. # * 每个组件都是“先检测,缺失才安装”,可重复执行(幂等)
  16. # * 支持仅检测:DETECT_ONLY=1 ./install_deps.sh
  17. # * 可指定要处理的组件:./install_deps.sh postgres mongo redis minio docker
  18. # 不带参数时处理默认集合:postgres mongo redis minio docker mc
  19. #
  20. # 环境变量:
  21. # MINIO_API_PORT MinIO S3 API 端口 (默认 9198)
  22. # MINIO_CONSOLE_PORT MinIO 控制台端口 (默认 9199)
  23. # MINIO_ROOT_USER MinIO 管理员用户 (默认 minioadmin)
  24. # MINIO_ROOT_PASSWORD MinIO 管理员密码 (默认 minioadmin)
  25. # GO_VERSION Go 版本 (默认 1.26.4)
  26. # =============================================================================
  27. set -euo pipefail
  28. MINIO_API_PORT="${MINIO_API_PORT:-9198}"
  29. MINIO_CONSOLE_PORT="${MINIO_CONSOLE_PORT:-9199}"
  30. # TODO: [必填] MinIO 管理员账户——请通过环境变量传入强口令,勿使用默认 minioadmin/minioadmin
  31. MINIO_ROOT_USER="${MINIO_ROOT_USER:-minioadmin}"
  32. MINIO_ROOT_PASSWORD="${MINIO_ROOT_PASSWORD:-minioadmin}"
  33. # TODO: [确认] Go 版本(仅在需要安装 Go 时用到)
  34. GO_VERSION="${GO_VERSION:-1.26.4}"
  35. DETECT_ONLY="${DETECT_ONLY:-0}"
  36. c_reset='\033[0m'; c_blue='\033[1;34m'; c_green='\033[1;32m'; c_yellow='\033[1;33m'; c_red='\033[1;31m'
  37. info() { echo -e "${c_blue}[INFO]${c_reset} $*"; }
  38. ok() { echo -e "${c_green}[ OK ]${c_reset} $*"; }
  39. warn() { echo -e "${c_yellow}[WARN]${c_reset} $*"; }
  40. err() { echo -e "${c_red}[FAIL]${c_reset} $*" >&2; }
  41. has() { command -v "$1" >/dev/null 2>&1; }
  42. # 仅检测时的统一处理:打印状态并返回,跳过安装
  43. _detect_guard() {
  44. # $1=组件名 $2=已安装(0/1) $3=版本串
  45. if [[ "$2" == "1" ]]; then
  46. ok "$1 已安装:$3"
  47. return 0 # 已装 -> 调用方 return
  48. fi
  49. if [[ "${DETECT_ONLY}" == "1" ]]; then
  50. warn "$1 未安装(仅检测模式,跳过安装)"
  51. return 0
  52. fi
  53. return 1 # 未装且需要安装 -> 调用方继续执行安装
  54. }
  55. apt_update_once() {
  56. if [[ -z "${_APT_UPDATED:-}" ]]; then
  57. sudo apt-get update -y
  58. _APT_UPDATED=1
  59. fi
  60. }
  61. # ---------------------------------------------------------------------------
  62. # PostgreSQL
  63. # ---------------------------------------------------------------------------
  64. ensure_postgres() {
  65. local ver=""
  66. has psql && ver="$(psql --version 2>/dev/null | awk '{print $3}')"
  67. _detect_guard "PostgreSQL" "$([[ -n $ver ]] && echo 1 || echo 0)" "${ver}" && return 0
  68. info "安装 PostgreSQL ..."
  69. apt_update_once
  70. sudo apt-get install -y postgresql postgresql-contrib
  71. sudo systemctl enable --now postgresql
  72. ok "PostgreSQL 安装完成:$(psql --version | awk '{print $3}')"
  73. }
  74. # ---------------------------------------------------------------------------
  75. # MongoDB 8.0
  76. # ---------------------------------------------------------------------------
  77. ensure_mongo() {
  78. local ver=""
  79. has mongod && ver="$(mongod --version 2>/dev/null | awk 'NR==1{print $3}')"
  80. _detect_guard "MongoDB" "$([[ -n $ver ]] && echo 1 || echo 0)" "${ver}" && return 0
  81. info "安装 MongoDB 8.0 ..."
  82. local codename; codename="$(. /etc/os-release && echo "${VERSION_CODENAME:-jammy}")"
  83. curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc \
  84. | sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor --yes
  85. echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu ${codename}/mongodb-org/8.0 multiverse" \
  86. | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list >/dev/null
  87. sudo apt-get update -y
  88. sudo apt-get install -y mongodb-org
  89. sudo systemctl enable --now mongod
  90. ok "MongoDB 安装完成"
  91. }
  92. # ---------------------------------------------------------------------------
  93. # Redis
  94. # ---------------------------------------------------------------------------
  95. ensure_redis() {
  96. local ver=""
  97. has redis-server && ver="$(redis-server --version 2>/dev/null | sed -E 's/.*v=([0-9.]+).*/\1/')"
  98. _detect_guard "Redis" "$([[ -n $ver ]] && echo 1 || echo 0)" "${ver}" && return 0
  99. info "安装 Redis ..."
  100. apt_update_once
  101. sudo apt-get install -y redis-server
  102. sudo systemctl enable --now redis-server
  103. ok "Redis 安装完成"
  104. }
  105. # ---------------------------------------------------------------------------
  106. # MinIO + mc
  107. # ---------------------------------------------------------------------------
  108. ensure_minio() {
  109. local ver=""
  110. has minio && ver="installed"
  111. if _detect_guard "MinIO" "$([[ -n $ver ]] && echo 1 || echo 0)" "$(command -v minio || true)"; then
  112. return 0
  113. fi
  114. info "安装 MinIO(二进制 + systemd)..."
  115. sudo wget -q -O /usr/local/bin/minio https://dl.min.io/server/minio/release/linux-amd64/minio
  116. sudo chmod +x /usr/local/bin/minio
  117. id minio-user >/dev/null 2>&1 || sudo useradd -r minio-user -s /sbin/nologin
  118. sudo mkdir -p /var/lib/minio/data
  119. sudo chown -R minio-user:minio-user /var/lib/minio
  120. sudo tee /etc/default/minio >/dev/null <<EOF
  121. MINIO_VOLUMES="/var/lib/minio/data"
  122. MINIO_OPTS="--address :${MINIO_API_PORT} --console-address :${MINIO_CONSOLE_PORT}"
  123. MINIO_ROOT_USER="${MINIO_ROOT_USER}"
  124. MINIO_ROOT_PASSWORD="${MINIO_ROOT_PASSWORD}"
  125. EOF
  126. sudo tee /etc/systemd/system/minio.service >/dev/null <<'EOF'
  127. [Unit]
  128. Description=MinIO
  129. Documentation=https://docs.min.io
  130. Wants=network-online.target
  131. After=network-online.target
  132. AssertFileIsExecutable=/usr/local/bin/minio
  133. [Service]
  134. Type=notify
  135. WorkingDirectory=/usr/local
  136. User=minio-user
  137. Group=minio-user
  138. EnvironmentFile=-/etc/default/minio
  139. ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
  140. Restart=always
  141. LimitNOFILE=1048576
  142. TasksMax=infinity
  143. OOMScoreAdjust=-1000
  144. [Install]
  145. WantedBy=multi-user.target
  146. EOF
  147. sudo systemctl daemon-reload
  148. sudo systemctl enable --now minio
  149. ok "MinIO 安装完成(API :${MINIO_API_PORT} / 控制台 :${MINIO_CONSOLE_PORT})"
  150. }
  151. ensure_mc() {
  152. local ver=""
  153. has mc && ver="installed"
  154. _detect_guard "mc(MinIO Client)" "$([[ -n $ver ]] && echo 1 || echo 0)" "$(command -v mc || true)" && return 0
  155. info "安装 mc(MinIO Client)..."
  156. sudo wget -q -O /usr/local/bin/mc https://dl.min.io/client/mc/release/linux-amd64/mc
  157. sudo chmod +x /usr/local/bin/mc
  158. ok "mc 安装完成"
  159. }
  160. # ---------------------------------------------------------------------------
  161. # Docker + Compose 插件(Casdoor 需要)
  162. # ---------------------------------------------------------------------------
  163. ensure_docker() {
  164. local ver=""
  165. has docker && ver="$(docker --version 2>/dev/null | awk '{print $3}' | tr -d ,)"
  166. _detect_guard "Docker" "$([[ -n $ver ]] && echo 1 || echo 0)" "${ver}" && return 0
  167. info "安装 Docker CE + compose 插件 ..."
  168. apt_update_once
  169. sudo apt-get install -y ca-certificates curl gnupg
  170. sudo install -m 0755 -d /etc/apt/keyrings
  171. curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  172. | sudo gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
  173. sudo chmod a+r /etc/apt/keyrings/docker.gpg
  174. local codename; codename="$(. /etc/os-release && echo "${VERSION_CODENAME:-jammy}")"
  175. echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu ${codename} stable" \
  176. | sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
  177. sudo apt-get update -y
  178. sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  179. sudo systemctl enable --now docker
  180. ok "Docker 安装完成:$(docker --version)"
  181. }
  182. # ---------------------------------------------------------------------------
  183. # Go / Node(仅构建时需要)
  184. # ---------------------------------------------------------------------------
  185. ensure_go() {
  186. local ver=""
  187. has go && ver="$(go version 2>/dev/null | awk '{print $3}')"
  188. _detect_guard "Go" "$([[ -n $ver ]] && echo 1 || echo 0)" "${ver}" && return 0
  189. info "安装 Go ${GO_VERSION} ..."
  190. wget -q "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -O /tmp/go.tgz
  191. sudo rm -rf /usr/local/go
  192. sudo tar -C /usr/local -xzf /tmp/go.tgz
  193. rm -f /tmp/go.tgz
  194. echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee /etc/profile.d/go.sh >/dev/null
  195. export PATH="$PATH:/usr/local/go/bin"
  196. ok "Go 安装完成:$(go version | awk '{print $3}')"
  197. }
  198. ensure_node() {
  199. local ver=""
  200. has node && ver="$(node -v 2>/dev/null)"
  201. _detect_guard "Node.js" "$([[ -n $ver ]] && echo 1 || echo 0)" "${ver}" && { has pnpm || { [[ ${DETECT_ONLY} == 1 ]] || { sudo npm install -g pnpm@8; ok "pnpm 安装完成"; }; }; return 0; }
  202. info "安装 Node.js 22 + pnpm ..."
  203. curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
  204. sudo apt-get install -y nodejs
  205. sudo npm install -g pnpm@8
  206. ok "Node/pnpm 安装完成:$(node -v) / pnpm $(pnpm -v)"
  207. }
  208. # ---------------------------------------------------------------------------
  209. # uv(Python 包/工具管理器,用于 uvx 拉起 MCP server 等)
  210. # ---------------------------------------------------------------------------
  211. ensure_uv() {
  212. local ver=""
  213. has uv && ver="$(uv --version 2>/dev/null | awk '{print $2}')"
  214. _detect_guard "uv" "$([[ -n $ver ]] && echo 1 || echo 0)" "${ver}" && return 0
  215. info "安装 uv(官方脚本,安装到 /usr/local/bin)..."
  216. # 官方安装脚本:用 UV_INSTALL_DIR 指定全局目录,--no-modify-path 避免改动 shell profile
  217. curl -LsSf https://astral.sh/uv/install.sh \
  218. | sudo env UV_INSTALL_DIR=/usr/local/bin UV_UNMANAGED_INSTALL=/usr/local/bin sh -s -- --no-modify-path
  219. if has uv; then
  220. ok "uv 安装完成:$(uv --version | awk '{print $2}')"
  221. else
  222. err "uv 安装后仍无法在 PATH 中找到,请检查 /usr/local/bin 是否在 PATH"
  223. return 1
  224. fi
  225. }
  226. # ---------------------------------------------------------------------------
  227. # 主流程
  228. # ---------------------------------------------------------------------------
  229. main() {
  230. local comps=("$@")
  231. [[ ${#comps[@]} -eq 0 ]] && comps=(postgres mongo redis minio mc docker)
  232. [[ "${DETECT_ONLY}" == "1" ]] && info "== 仅检测模式 ==" || info "== 检测并安装缺失组件 =="
  233. for c in "${comps[@]}"; do
  234. case "${c}" in
  235. postgres|pg) ensure_postgres ;;
  236. mongo|mongodb) ensure_mongo ;;
  237. redis) ensure_redis ;;
  238. minio) ensure_minio ;;
  239. mc) ensure_mc ;;
  240. docker) ensure_docker ;;
  241. go) ensure_go ;;
  242. node) ensure_node ;;
  243. uv) ensure_uv ;;
  244. *) warn "未知组件:${c}(可选:postgres mongo redis minio mc docker go node uv)" ;;
  245. esac
  246. done
  247. ok "依赖处理完成"
  248. }
  249. main "$@"