把docker-compose之类的服务维护到systemd中去,手动有点麻烦,搞个脚本。
1#!/bin/bash
2
3# ==============================================================================
4# Docker Compose Systemd 服务交互式配置工具
5# ==============================================================================
6# 描述: 此脚本将引导用户为多个 Docker Compose 项目创建 systemd 服务,
7# 从而实现应用的开机自启动和便捷管理。
8# 版本: 1.0
9# 作者: Gemini Assistant
10# 日期: 2025-06-02
11# ==============================================================================
12
13# --- 配置项 (通常无需修改) ---
14# 默认的 docker-compose 命令路径。如果系统找不到,将尝试此路径。
15DEFAULT_DOCKER_COMPOSE_CMD="/usr/local/bin/docker-compose"
16
17# --- 辅助函数 ---
18
19# 检查指定命令是否存在于 PATH 中
20command_exists () {
21 command -v "$1" >/dev/null 2>&1
22}
23
24# 提示用户输入,并可选地进行路径或文件存在性验证
25get_input() {
26 local prompt="$1" # 提示信息
27 local var_name="$2" # 存储用户输入的变量名
28 local default_val="$3" # 默认值 (可选)
29 local check_type="$4" # 检查类型: 'dir' (目录), 'file' (文件), '' (无检查)
30
31 while true; do
32 if [ -n "$default_val" ]; then
33 read -rp "$prompt [$default_val]: " input
34 else
35 read -rp "$prompt: " input
36 fi
37 input="${input:-$default_val}" # 如果用户输入为空,则使用默认值
38
39 if [ -z "$input" ]; then
40 echo "输入不能为空,请重新输入。"
41 continue
42 fi
43
44 case "$check_type" in
45 "dir")
46 if [ ! -d "$input" ]; then
47 echo "错误:路径 '$input' 不存在或不是一个目录。请重新输入。"
48 continue
49 fi
50 # 对于 Docker Compose 项目目录,额外检查是否存在 docker-compose.yml
51 if [ ! -f "$input/docker-compose.yml" ] && [ ! -f "$input/docker-compose.yaml" ]; then
52 echo "警告:在 '$input' 中找不到 'docker-compose.yml' 或 'docker-compose.yaml' 文件。"
53 read -rp "您确定要使用此路径吗?(y/N): " confirm_path
54 if [[ ! "$confirm_path" =~ ^[yY]$ ]]; then
55 continue
56 fi
57 fi
58 ;;
59 "file")
60 if [ ! -f "$input" ]; then
61 echo "错误:文件 '$input' 不存在。请重新输入。"
62 continue
63 fi
64 ;;
65 *)
66 # 无需特定检查
67 ;;
68 esac
69
70 # 将输入的值赋给指定的变量名
71 eval "$var_name='$input'"
72 break
73 done
74}
75
76# --- 主要逻辑 ---
77
78main() {
79 echo "--- 欢迎使用 Docker Compose Systemd 服务交互式配置工具 ---"
80 echo "此脚本将帮助您为多个 Docker Compose 项目创建 systemd 服务,实现开机自启动和便捷管理。"
81 echo ""
82
83 # 1. 检查 docker-compose 命令路径
84 echo "步骤 1/4: 检查 Docker Compose 命令路径..."
85 local docker_compose_cmd_found=false
86 if command_exists "docker-compose"; then
87 DOCKER_COMPOSE_CMD=$(command -v docker-compose)
88 docker_compose_cmd_found=true
89 echo "✅ 检测到 'docker-compose' 命令路径: $DOCKER_COMPOSE_CMD"
90 else
91 echo "⚠️ 警告:未在 PATH 中找到 'docker-compose' 命令。"
92 echo " 脚本将尝试使用默认路径: $DEFAULT_DOCKER_COMPOSE_CMD"
93 DOCKER_COMPOSE_CMD="$DEFAULT_DOCKER_COMPOSE_CMD"
94
95 read -rp " 您是否希望手动指定 'docker-compose' 命令的完整路径?(y/N): " confirm_path_change
96 if [[ "$confirm_path_change" =~ ^[yY]$ ]]; then
97 get_input " 请输入正确的 'docker-compose' 命令完整路径" DOCKER_COMPOSE_CMD "$DOCKER_COMPOSE_CMD" "file"
98 fi
99
100 if [ ! -f "$DOCKER_COMPOSE_CMD" ]; then
101 echo "❌ 错误:指定的 Docker Compose 命令 '$DOCKER_COMPOSE_CMD' 不存在。"
102 echo " 请确保 Docker Compose 已正确安装并可执行。"
103 exit 1
104 fi
105 echo "✅ 将使用 'docker-compose' 命令路径: $DOCKER_COMPOSE_CMD"
106 fi
107 echo ""
108
109 # 存储所有已成功配置的服务名称
110 declare -a configured_services
111
112 # 2. 循环配置每个 Docker Compose 项目
113 while true; do
114 echo "--- 开始配置新的 Docker Compose 项目 ---"
115
116 local current_project_path
117 local current_service_name
118 local current_service_description
119
120 # 获取项目路径
121 get_input "请输入 Docker Compose 项目的**绝对路径** (例如: /opt/my-app)" current_project_path "" "dir"
122
123 # 生成并获取服务名称
124 # 尝试根据项目路径的最后一个目录名生成默认服务名称
125 local default_service_name
126 default_service_name=$(basename "$current_project_path" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]/-/g' | sed 's/^-*//' | sed 's/-*$//')
127 get_input "请输入此服务的名称 (例如: my-web-app)。这将是 systemd 服务文件名" current_service_name "$default_service_name" ""
128
129 # 检查服务名称是否重复
130 if [[ " ${configured_services[*]} " =~ " ${current_service_name} " ]]; then
131 echo "❌ 错误:服务名称 '$current_service_name' 已被使用,请使用不同的名称。"
132 continue # 重新开始当前项目的配置
133 fi
134
135 # 获取服务描述
136 get_input "请输入此服务的简短描述 (例如: My Web Application)" current_service_description "My Docker Compose Service" ""
137
138 local service_file="/etc/systemd/system/${current_service_name}.service"
139
140 echo ""
141 echo "--- 确认当前项目配置 ---"
142 echo "项目路径: $current_project_path"
143 echo "服务名称: $current_service_name"
144 echo "服务描述: $current_service_description"
145 echo "将创建的服务文件: $service_file"
146 echo "使用的 Docker Compose: $DOCKER_COMPOSE_CMD"
147 read -rp "以上信息确认无误?(y/N): " confirm_config
148 if [[ ! "$confirm_config" =~ ^[yY]$ ]]; then
149 echo "ℹ️ 取消当前项目的配置,请重新输入。"
150 continue # 重新开始当前项目的配置
151 fi
152
153 # 3. 创建 systemd 服务文件
154 echo ""
155 echo "步骤 2/4: 正在创建 systemd 服务文件:$service_file..."
156 local service_file_content="[Unit]
157Description=$current_service_description
158Requires=docker.service
159After=docker.service network-online.target
160
161[Service]
162Type=oneshot
163RemainAfterExit=yes
164WorkingDirectory=$current_project_path
165ExecStart=$DOCKER_COMPOSE_CMD up -d --remove-orphans
166ExecStop=$DOCKER_COMPOSE_CMD down
167ExecReload=$DOCKER_COMPOSE_CMD pull --quiet --parallel && $DOCKER_COMPOSE_CMD up -d
168
169[Install]
170WantedBy=multi-user.target
171"
172 echo "$service_file_content" | sudo tee "$service_file" > /dev/null
173
174 if [ $? -eq 0 ]; then
175 echo "✅ 服务文件创建成功。"
176 else
177 echo "❌ 错误:创建服务文件失败。请检查权限。"
178 read -rp "是否继续配置其他服务?(y/N): " continue_others
179 if [[ ! "$continue_others" =~ ^[yY]$ ]]; then break; fi
180 continue
181 fi
182
183 # 4. 重新加载 systemd 配置,启用并启动服务
184 echo "步骤 3/4: 重新加载 systemd 配置..."
185 sudo systemctl daemon-reload
186 if [ $? -eq 0 ]; then
187 echo "✅ systemd 配置重新加载成功。"
188 else
189 echo "❌ 错误:systemd 配置重新加载失败。"
190 read -rp "是否继续配置其他服务?(y/N): " continue_others
191 if [[ ! "$continue_others" =~ ^[yY]$ ]]; then break; fi
192 continue
193 fi
194
195 echo "步骤 4/4: 启用服务 ($current_service_name) 以便开机自启动..."
196 sudo systemctl enable "$current_service_name.service"
197 if [ $? -eq 0 ]; then
198 echo "✅ 服务已成功启用,将在系统启动时自动运行。"
199 else
200 echo "❌ 错误:启用服务失败。"
201 read -rp "是否继续配置其他服务?(y/N): " continue_others
202 if [[ ! "$continue_others" =~ ^[yY]$ ]]; then break; fi
203 continue
204 fi
205
206 echo "立即启动服务 ($current_service_name)..."
207 sudo systemctl start "$current_service_name.service"
208 if [ $? -eq 0 ]; then
209 echo "✅ 服务已成功启动。"
210 else
211 echo "❌ 错误:启动服务失败。请检查日志:sudo journalctl -u $current_service_name.service"
212 read -rp "是否继续配置其他服务?(y/N): " continue_others
213 if [[ ! "$continue_others" =~ ^[yY]$ ]]; then break; fi
214 continue
215 fi
216
217 # 将成功配置的服务名称添加到列表中
218 configured_services+=("$current_service_name")
219 echo ""
220 read -rp "成功配置 '$current_service_name'。是否需要配置另一个 Docker Compose 项目?(y/N): " another_project
221 if [[ ! "$another_project" =~ ^[yY]$ ]]; then
222 break # 退出循环
223 fi
224 echo "" # 打印空行以分隔不同项目的配置
225 done
226
227 # --- 总结与后续操作提示 ---
228 echo ""
229 echo "--- 所有 Docker Compose 服务配置完成! ---"
230 if [ ${#configured_services[@]} -gt 0 ]; then
231 echo "已成功配置以下服务:"
232 for svc in "${configured_services[@]}"; do
233 echo " - ${svc}.service"
234 done
235 echo ""
236 echo "你可以使用以下命令来管理这些服务:"
237 echo " - **查看所有 Docker Compose 服务的状态:**"
238 echo " systemctl list-units --type=service | grep \"docker-compose\\|${configured_services[0]}\" # 或 grep 你服务名称的共同模式"
239 echo " - **查看特定服务状态** (例如: ${configured_services[0]}.service):"
240 echo " sudo systemctl status ${configured_services[0]}.service"
241 echo " - **启动特定服务** (例如: ${configured_services[0]}.service):"
242 echo " sudo systemctl start ${configured_services[0]}.service"
243 echo " - **停止特定服务** (例如: ${configured_services[0]}.service):"
244 echo " sudo systemctl stop ${configured_services[0]}.service"
245 echo " - **重启特定服务** (例如: ${configured_services[0]}.service):"
246 echo " sudo systemctl restart ${configured_services[0]}.service"
247 echo " - **查看特定服务日志** (例如: ${configured_services[0]}.service):"
248 echo " sudo journalctl -u ${configured_services[0]}.service -f"
249 echo " - **禁用特定服务的开机自启动** (例如: ${configured_services[0]}.service):"
250 echo " sudo systemctl disable ${configured_services[0]}.service"
251 else
252 echo "没有成功配置任何服务。"
253 fi
254 echo ""
255 echo "脚本执行完毕。感谢您的使用!"
256}
257
258# 运行主函数
259main "$@"