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

603 lines
16 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
# 日系动漫风格404页面一键部署脚本 - 修复版
# 适用于Nginx反向代理环境
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"
}
# 检查Nginx是否安装修复版
check_nginx() {
log_info "检查Nginx安装状态..."
# 多种方式检查Nginx
if command -v nginx &> /dev/null; then
log_success "通过command命令检测到Nginx"
return 0
fi
if systemctl is-active --quiet nginx 2>/dev/null; then
log_success "通过systemctl检测到Nginx服务正在运行"
return 0
fi
if ps aux | grep -v grep | grep nginx &> /dev/null; then
log_success "通过进程检测到Nginx正在运行"
return 0
fi
if [ -f /usr/sbin/nginx ] || [ -f /usr/local/nginx/sbin/nginx ]; then
log_success "通过文件路径检测到Nginx"
return 0
fi
log_warning "未检测到Nginx但继续执行可能是自定义安装"
return 0
}
# 创建404页面
create_404_page() {
local html_path="/usr/share/nginx/html/404.html"
local custom_path="/var/www/html/404.html"
log_info "正在创建日系动漫风格404页面..."
# 尝试多个可能的HTML目录
for path in "$html_path" "$custom_path"; do
local dir=$(dirname "$path")
if [ -d "$dir" ]; then
html_path="$path"
log_info "使用HTML目录: $dir"
break
fi
done
# 如果目录不存在,创建它
local dir=$(dirname "$html_path")
if [ ! -d "$dir" ]; then
log_warning "目录 $dir 不存在,正在创建..."
mkdir -p "$dir"
fi
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"
}
# 查找Nginx配置目录
find_nginx_config() {
log_info "查找Nginx配置目录..."
local possible_paths=(
"/etc/nginx"
"/usr/local/nginx/conf"
"/usr/local/etc/nginx"
)
for path in "${possible_paths[@]}"; do
if [ -d "$path" ]; then
echo "$path"
log_success "找到Nginx配置目录: $path"
return 0
fi
done
log_error "未找到Nginx配置目录"
return 1
}
# 配置Nginx
configure_nginx() {
log_info "正在配置Nginx..."
local nginx_conf_dir=$(find_nginx_config)
if [ $? -ne 0 ]; then
log_error "无法找到Nginx配置目录"
return 1
fi
local sites_available_dir="$nginx_conf_dir/sites-available"
local sites_enabled_dir="$nginx_conf_dir/sites-enabled"
local conf_d_dir="$nginx_conf_dir/conf.d"
# 创建404配置片段
local error_conf="$nginx_conf_dir/conf.d/custom_errors.conf"
cat > "$error_conf" << 'EOF'
# 自定义错误页面配置
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /404.html {
root /usr/share/nginx/html;
internal;
}
location = /50x.html {
root /usr/share/nginx/html;
internal;
}
EOF
log_success "已创建错误页面配置: $error_conf"
# 如果存在sites-available目录也为每个站点配置
if [ -d "$sites_available_dir" ]; then
for config_file in "$sites_available_dir"/*; do
if [[ -f "$config_file" && ! -L "$config_file" ]]; then
local config_name=$(basename "$config_file")
log_info "检查站点配置: $config_name"
# 备份原配置
cp "$config_file" "$config_file.backup.$(date +%Y%m%d%H%M%S)"
# 检查是否已存在404配置
if ! grep -q "error_page 404" "$config_file"; then
# 在server块中添加404配置
if grep -q "server {" "$config_file"; then
sed -i '/server {/a\\n # 自定义错误页面\n error_page 404 /404.html;\n location = /404.html {\n root /usr/share/nginx/html;\n internal;\n }' "$config_file"
log_success "已为 $config_name 添加404配置"
fi
else
log_info "$config_name 已有404配置跳过"
fi
fi
done
fi
}
# 测试Nginx配置
test_nginx() {
log_info "测试Nginx配置..."
if nginx -t 2>/dev/null || /usr/local/nginx/sbin/nginx -t 2>/dev/null; then
log_success "Nginx配置测试通过"
return 0
else
log_error "Nginx配置测试失败"
return 1
fi
}
# 重新加载Nginx
reload_nginx() {
log_info "重新加载Nginx配置..."
# 多种方式重载Nginx
if systemctl reload nginx 2>/dev/null; then
log_success "通过systemctl重新加载Nginx"
return 0
fi
if service nginx reload 2>/dev/null; then
log_success "通过service重新加载Nginx"
return 0
fi
if nginx -s reload 2>/dev/null; then
log_success "通过nginx命令重新加载Nginx"
return 0
fi
log_warning "无法自动重新加载Nginx请手动执行: nginx -s reload"
return 1
}
# 显示完成信息
show_completion() {
echo
log_success "日系动漫风格404页面部署完成"
echo
log_info "部署详情:"
log_info "- 404页面位置: /usr/share/nginx/html/404.html"
log_info "- Nginx配置已更新"
log_info "- 创建了自定义错误页面配置"
echo
log_info "您可以通过访问一个不存在的URL来测试404页面"
log_info "例如: curl http://your-domain/not-exist-page"
echo
log_warning "如果页面未立即生效请手动重启Nginx服务"
}
# 主函数
main() {
echo
log_info "开始部署日系动漫风格404页面..."
echo
# 检查环境
check_nginx
# 执行部署步骤
create_404_page
configure_nginx
# 测试并重新加载Nginx
if test_nginx; then
reload_nginx
show_completion
else
log_error "部署失败请检查Nginx配置"
exit 1
fi
}
# 显示使用说明
usage() {
echo "日系动漫风格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