Files
dock/404
2025-10-31 00:16:16 +08:00

543 lines
14 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Docker环境日系动漫风格404页面一键部署脚本
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查Docker环境
check_docker_nginx() {
log_info "检查Docker Nginx容器..."
# 查找运行的Nginx容器
local nginx_container=$(docker ps --filter "name=nginx" --format "{{.Names}}" | head -1)
if [ -z "$nginx_container" ]; then
nginx_container=$(docker ps --filter "publish=80" --format "{{.Names}}" | head -1)
fi
if [ -z "$nginx_container" ]; then
nginx_container=$(docker ps --filter "publish=443" --format "{{.Names}}" | head -1)
fi
if [ -n "$nginx_container" ]; then
log_success "找到Nginx容器: $nginx_container"
echo "$nginx_container"
return 0
else
log_error "未找到运行的Nginx容器"
return 1
fi
}
# 创建404页面到宿主机目录
create_404_page() {
local host_data_dir="/boot/data/dataxn"
log_info "正在创建日系动漫风格404页面..."
# 检查宿主机目录是否存在
if [ ! -d "$host_data_dir" ]; then
log_warning "目录 $host_data_dir 不存在,正在创建..."
mkdir -p "$host_data_dir"
fi
local html_path="$host_data_dir/404.html"
cat > "$html_path" << 'EOF'
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>页面未找到 - 404错误</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial Rounded MT Bold', 'Hiragino Maru Gothic ProN', 'Yu Gothic', sans-serif;
}
body {
background: linear-gradient(135deg, #ffdde1 0%, #ee9ca7 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
color: #5a3d5c;
}
.container {
max-width: 800px;
width: 100%;
background-color: rgba(255, 255, 255, 0.85);
border-radius: 25px;
padding: 40px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
text-align: center;
position: relative;
overflow: hidden;
border: 3px solid #ffb6c1;
}
.anime-character {
width: 180px;
height: 200px;
margin: 0 auto 20px;
position: relative;
}
.character-head {
width: 120px;
height: 120px;
background-color: #fff;
border-radius: 50%;
margin: 0 auto;
position: relative;
border: 3px solid #ffb6c1;
z-index: 2;
}
.character-hair {
width: 140px;
height: 80px;
background-color: #ff69b4;
border-radius: 70px 70px 0 0;
position: absolute;
top: -20px;
left: 50%;
transform: translateX(-50%);
z-index: 1;
}
.character-eyes {
display: flex;
justify-content: space-around;
width: 80px;
margin: 40px auto 0;
}
.eye {
width: 20px;
height: 30px;
background-color: #5a3d5c;
border-radius: 50%;
position: relative;
overflow: hidden;
}
.eye::after {
content: '';
position: absolute;
width: 10px;
height: 10px;
background-color: white;
border-radius: 50%;
top: 5px;
left: 5px;
}
.character-mouth {
width: 30px;
height: 10px;
background-color: #ff69b4;
border-radius: 0 0 15px 15px;
margin: 15px auto 0;
}
.character-body {
width: 100px;
height: 80px;
background-color: #ffb6c1;
border-radius: 20px 20px 0 0;
margin: -10px auto 0;
position: relative;
z-index: 1;
}
.error-code {
font-size: 120px;
font-weight: bold;
color: #ff69b4;
text-shadow: 3px 3px 0 #ffb6c1;
margin: 10px 0;
line-height: 1;
}
h1 {
font-size: 32px;
margin-bottom: 20px;
color: #5a3d5c;
}
p {
font-size: 18px;
line-height: 1.6;
margin-bottom: 30px;
color: #7a5c7d;
}
.action-buttons {
display: flex;
justify-content: center;
gap: 15px;
flex-wrap: wrap;
}
.btn {
padding: 12px 25px;
border-radius: 50px;
text-decoration: none;
font-weight: bold;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
cursor: pointer;
font-size: 16px;
}
.btn-primary {
background-color: #ff69b4;
color: white;
box-shadow: 0 4px 0 #d4508f;
}
.btn-secondary {
background-color: #b19cd9;
color: white;
box-shadow: 0 4px 0 #8a7bb5;
}
.btn:hover {
transform: translateY(-3px);
box-shadow: 0 6px 0 rgba(0, 0, 0, 0.2);
}
.btn:active {
transform: translateY(1px);
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.2);
}
.floating-elements {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
pointer-events: none;
}
.floating-element {
position: absolute;
opacity: 0.7;
animation: float 6s ease-in-out infinite;
}
.element-1 {
top: 10%;
left: 5%;
animation-delay: 0s;
}
.element-2 {
top: 20%;
right: 10%;
animation-delay: 2s;
}
.element-3 {
bottom: 30%;
left: 15%;
animation-delay: 4s;
}
@keyframes float {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-20px);
}
}
.sparkle {
position: absolute;
width: 20px;
height: 20px;
background-color: #fff;
border-radius: 50%;
opacity: 0;
animation: sparkle 3s linear infinite;
}
@keyframes sparkle {
0%, 100% {
opacity: 0;
transform: scale(0);
}
50% {
opacity: 1;
transform: scale(1);
}
}
@media (max-width: 600px) {
.container {
padding: 25px;
}
.error-code {
font-size: 80px;
}
h1 {
font-size: 24px;
}
p {
font-size: 16px;
}
.action-buttons {
flex-direction: column;
align-items: center;
}
.btn {
width: 100%;
max-width: 250px;
}
}
</style>
</head>
<body>
<div class="container">
<div class="floating-elements">
<div class="floating-element element-1">🌸</div>
<div class="floating-element element-2">⭐</div>
<div class="floating-element element-3">🐱</div>
</div>
<div class="anime-character">
<div class="character-hair"></div>
<div class="character-head">
<div class="character-eyes">
<div class="eye"></div>
<div class="eye"></div>
</div>
<div class="character-mouth"></div>
</div>
<div class="character-body"></div>
</div>
<div class="error-code">404</div>
<h1>おっと!ページが見つかりません</h1>
<p>申し訳ありませんが、お探しのページは存在しないか、移動した可能性があります。<br>
迷子になったキャラクターのように、ページもどこかへ行ってしまったようです。</p>
<div class="action-buttons">
<a href="/" class="btn btn-primary">ホームに戻る</a>
<a href="javascript:history.back()" class="btn btn-secondary">前のページに戻る</a>
</div>
</div>
<script>
// 添加闪烁效果
document.addEventListener('DOMContentLoaded', function() {
const container = document.querySelector('.container');
for (let i = 0; i < 15; i++) {
const sparkle = document.createElement('div');
sparkle.classList.add('sparkle');
// 随机位置
sparkle.style.left = Math.random() * 100 + '%';
sparkle.style.top = Math.random() * 100 + '%';
// 随机大小
const size = Math.random() * 10 + 5;
sparkle.style.width = size + 'px';
sparkle.style.height = size + 'px';
// 随机延迟
sparkle.style.animationDelay = Math.random() * 5 + 's';
container.appendChild(sparkle);
}
});
</script>
</body>
</html>
EOF
log_success "404页面已创建: $html_path"
}
# 为Docker容器创建Nginx配置
create_nginx_config() {
local container_name="$1"
log_info "为容器 $container_name 创建Nginx配置..."
# 检查容器内的Nginx配置路径
local nginx_conf_path="/etc/nginx/conf.d/custom_404.conf"
# 创建配置内容
local config_content=$(cat << 'EOF'
# 自定义404错误页面配置
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
internal;
allow all;
}
EOF
)
# 将配置写入容器
echo "$config_content" | docker exec -i "$container_name" tee "$nginx_conf_path" > /dev/null
if [ $? -eq 0 ]; then
log_success "Nginx配置已写入容器: $nginx_conf_path"
else
log_error "无法写入容器配置,请检查容器权限"
return 1
fi
}
# 测试Nginx配置
test_nginx_config() {
local container_name="$1"
log_info "测试容器Nginx配置..."
if docker exec "$container_name" nginx -t; then
log_success "Nginx配置测试通过"
return 0
else
log_error "Nginx配置测试失败"
return 1
fi
}
# 重新加载Nginx
reload_nginx() {
local container_name="$1"
log_info "重新加载容器Nginx配置..."
if docker exec "$container_name" nginx -s reload; then
log_success "Nginx配置已重新加载"
return 0
else
log_error "Nginx重新加载失败"
return 1
fi
}
# 显示Docker特定信息
show_docker_info() {
local container_name="$1"
echo
log_success "日系动漫风格404页面部署完成"
echo
log_info "部署详情:"
log_info "- 宿主机404页面: /boot/data/dataxn/404.html"
log_info "- Nginx容器: $container_name"
log_info "- 容器内配置: /etc/nginx/conf.d/custom_404.conf"
echo
log_info "目录映射关系:"
log_info "- 宿主机: /boot/data/dataxn → 容器: (请检查您的具体映射路径)"
echo
log_info "测试方法:"
log_info "1. 访问一个不存在的页面: curl http://your-domain/not-exist-page"
log_info "2. 或直接在浏览器中访问不存在的URL"
echo
log_warning "如果您的目录映射不是默认的/usr/share/nginx/html请手动调整配置"
}
# 主函数
main() {
echo
log_info "开始为Docker Nginx部署日系动漫风格404页面..."
echo
# 检查Docker环境
local container_name=$(check_docker_nginx)
if [ $? -ne 0 ]; then
exit 1
fi
# 执行部署步骤
create_404_page
create_nginx_config "$container_name"
# 测试并重新加载Nginx
if test_nginx_config "$container_name"; then
reload_nginx "$container_name"
show_docker_info "$container_name"
else
log_error "部署失败请检查Nginx配置"
exit 1
fi
}
# 显示使用说明
usage() {
echo "Docker环境日系动漫风格404页面一键部署脚本"
echo
echo "使用方法: $0 [选项]"
echo
echo "选项:"
echo " -h, --help 显示此帮助信息"
echo " -i, --install 执行安装部署"
echo
echo "示例:"
echo " $0 --install 部署404页面"
}
# 参数处理
case "${1:-}" in
-h|--help)
usage
exit 0
;;
-i|--install|"")
main
;;
*)
log_error "未知选项: $1"
usage
exit 1
;;
esac