Mysql安装

2023/4/5 Install

# 账号准备

# 1.新建用户

sudo useradd -m -d /home/包名 -s /bin/bash 用户名
1

# 2.设置密码

passwd 用户名
1

# 准备依赖

链接:https://pan.baidu.com/s/1lXNp0Ds4nDmAgguq6S3LRw?pwd=z6xy 
提取码:z6xy
1
2

# 执行部署

# 1.解压安装包

tar -zxf mysql-8.0.31-el7-x86_64.tar.gz
1

# 2.重命名安装目录

mv mysql-8.0.31-el7-x86_64/ mysql-8.0.31/
1

# 3.进入安装目录

cd mysql-8.0.31/
1

# 4.创建各必要目录

mkdir data/ tmp/ logs/ binlog/ backup/
1

# 5.修改mysql配置文件 [my.cnf]

链接:https://pan.baidu.com/s/1Z3i7w0FxfbbgAA28qyO21w?pwd=wzbg 
提取码:wzbg

#直接放在mysql-8.0.31/目录下
vim my.cnf
1
2
3
4
5

# 6.执行初始化命令

#可能需要建立软连接, /etc/my.cnf

bin/mysqld --initialize-insecure
1
2
3

# 7.启动MySQL服务进程

bin/mysqld_safe --defaults-file=my.cnf &
1

# 8.编写启动文件start.sh

#!/bin/bash

nohup bin/mysqld_safe --defaults-file=my.cnf >nohup.out 2>&1 &
echo "mysql-server started!"
1
2
3
4

# 9.使用客户端登录mysql

bin/mysql -u root -p --socket=mysql.sock
1

# 10.设置root密码

#三种方式
set password for root@localhost = password('********');

bin/mysqladmin -u root password "newpass"

alter user 'root'@'localhost' identified by 'Root@my123';
1
2
3
4
5
6

# 11.创建数据库

mysql> create database nssap;
1

# 12.创建用户

mysql> create user 'mysql'@'%' identified by 'mysql@123';
1

# 13.授予数据库全部权限

mysql> grant all privileges on mysql.* to 'mysql'@'%';
1

# 14.刷新权限

mysql> flush privileges;
mysql> exit;
1
2

# 15.执行数据库初始化

bin/mysql -u mysql -p mysql <dbchangelock.sql
1

# 测试部署

# 1.查看MySQL进程是否存在

ps -ef|grep mysql|grep -v grep
1

# 2.查询数据库

bin/mysql -u mysql -p

mysql> show tables;
1
2
3

# 编写备份脚本

# 1. 配置文件格式

创建一个名为 db_config.conf 的配置文件:

将此文件保存在安全位置,例如 /home/mysql/conf/db_config.conf

# 数据库连接配置
# 请确保此文件权限设置为 600 (chmod 600 db_config.conf)

DB_HOST="数据库地址"
DB_PORT="数据库端口"
DB_NAME="数据库名"
DB_USER="用户名"
DB_PASSWORD="密码"

# MySQL安装路径
MYSQL_HOME="/home/mysql/mysql-8.0.33"

# 备份文件存储目录
BACKUP_DIR="/home/mysql/mysql_backup"

# 日志文件目录
LOG_DIR=/home/mysql/mysql_backup/logs"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2. 设置文件权限

chmod 600 /home/mysql/conf/db_config.conf
chown mysql:mysql /home/mysql/conf/db_config.conf
1
2

# 3.备份脚本

#!/bin/bash
#saltedFish
#备份mysql数据库并删除n天前的备份

# 设置错误退出
set -e

# 配置文件路径
CONFIG_FILE="/home/mysql/conf/db_config.conf"
# 日志文件配置
MAX_LOG_DAYS=90  # 保留n天的日志
# 备份文件名,包含日期
DATE=$(date +%Y%m%d_%H%M%S)

# 检查配置文件是否存在且可读
check_config_file() {
    if [ ! -f "$CONFIG_FILE" ]; then
        echo "错误: 配置文件不存在: $CONFIG_FILE" >&2
        exit 1
    fi
    
    if [ ! -r "$CONFIG_FILE" ]; then
        echo "错误: 配置文件不可读: $CONFIG_FILE" >&2
        exit 1
    fi
    
    # 检查文件权限是否安全 (应该只有所有者可读)
    local file_perm=$(stat -c "%a" "$CONFIG_FILE" 2>/dev/null || stat -f "%A" "$CONFIG_FILE" 2>/dev/null)
    if [ "$file_perm" != "600" ]; then
        echo "警告: 配置文件权限不安全 (当前: $file_perm, 建议: 600)" >&2
    fi
}

# 加载配置文件
load_config() {
    # 安全地source配置文件,避免执行任意代码
    while IFS='=' read -r key value; do
        # 跳过注释行和空行
        if [[ $key =~ ^[[:space:]]*# ]] || [[ -z $key ]] || [[ $key =~ ^[[:space:]]*$ ]]; then
            continue
        fi
        
        # 移除值部分的引号
        value=$(echo "$value" | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//")
        
        # 只设置预期的变量
        case $key in
            DB_HOST|DB_PORT|DB_NAME|DB_USER|DB_PASSWORD|MYSQL_HOME|BACKUP_DIR|LOG_DIR)
                eval "$key=\"$value\""
                ;;
            *)
                echo "警告: 忽略未知配置项: $key" >&2
                ;;
        esac
    done < "$CONFIG_FILE"
}

# 创建必要的目录(在加载配置后调用)
create_directories() {
    mkdir -p "$BACKUP_DIR"
    mkdir -p "$LOG_DIR"
}

# 设置日志文件路径(在加载配置后调用)
setup_log_file() {
    LOG_FILE="$LOG_DIR/backup_$(date +%Y%m%d).log"
    BACKUP_FILE="$BACKUP_DIR/csa.$DATE.sql.gz"
}

# 日志函数
log() {
    local level="$1"
    local message="$2"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local log_entry="[$timestamp] [$level] $message"
    
    # 输出到控制台
    echo "$log_entry"
    
    # 输出到日志文件
    echo "$log_entry" >> "$LOG_FILE"
}

# 检查必要命令是否存在
check_commands() {
    log "INFO" "检查必要命令..."
    local commands=("gzip" "find")
    for cmd in "${commands[@]}"; do
        if ! command -v "$cmd" &> /dev/null; then
            log "ERROR" "命令 $cmd 不存在"
            exit 1
        fi
        log "DEBUG" "命令检查通过: $cmd"
    done
    
    if [ ! -f "$MYSQL_HOME/bin/mysqldump" ]; then
        log "ERROR" "mysqldump 不存在于 $MYSQL_HOME/bin/"
        exit 1
    fi
    log "DEBUG" "mysqldump 检查通过: $MYSQL_HOME/bin/mysqldump"
}

# 创建备份目录
create_backup_dir() {
    log "INFO" "检查备份目录..."
    if [ ! -d "$BACKUP_DIR" ]; then
        log "INFO" "创建备份目录: $BACKUP_DIR"
        if ! mkdir -p "$BACKUP_DIR"; then
            log "ERROR" "无法创建备份目录"
            exit 1
        fi
    fi
    
    # 检查目录权限
    if [ ! -w "$BACKUP_DIR" ]; then
        log "ERROR" "备份目录不可写"
        exit 1
    fi
    log "DEBUG" "备份目录检查通过: $BACKUP_DIR"
}

# 备份数据库
backup_database() {
    log "INFO" "开始备份数据库 $DB_NAME..."
    
    # 使用更安全的方式传递密码
    export MYSQL_PWD="$DB_PASSWORD"
    
    # 记录备份开始时间
    local start_time=$(date +%s)
    
    # 执行备份
    log "INFO" "执行 mysqldump 命令..."
    if ! "$MYSQL_HOME/bin/mysqldump" -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" \
        --single-transaction \
        --routines \
        --events \
        --add-drop-database \
        --databases "$DB_NAME" 2>> "$LOG_FILE" | gzip > "$BACKUP_FILE" 2>> "$LOG_FILE"; then
        log "ERROR" "数据库备份失败"
        unset MYSQL_PWD
        exit 1
    fi
    
    unset MYSQL_PWD
    
    # 计算备份耗时
    local end_time=$(date +%s)
    local duration=$((end_time - start_time))
    
    # 检查备份文件是否创建成功
    if [ ! -f "$BACKUP_FILE" ]; then
        log "ERROR" "备份文件未创建"
        exit 1
    fi
    
    # 检查备份文件大小
    local file_size=$(stat -c%s "$BACKUP_FILE" 2>/dev/null || stat -f%z "$BACKUP_FILE" 2>/dev/null)
    if [ "$file_size" -eq 0 ]; then
        log "ERROR" "备份文件为空"
        rm -f "$BACKUP_FILE"
        exit 1
    fi
    
    # 获取文件大小(人类可读格式)
    local human_size=$(du -h "$BACKUP_FILE" | cut -f1)
    
    log "INFO" "备份成功: $BACKUP_FILE"
    log "INFO" "备份大小: $human_size, 耗时: ${duration}秒"
}

# 清理旧备份
cleanup_old_backups() {
    log "INFO" "开始清理超过30天的备份文件..."
    
    local deleted_count=0
    local error_count=0
    
    # 查找并删除旧备份文件
    while IFS= read -r -d '' file; do
        if rm -f "$file"; then
            log "INFO" "删除备份文件: $(basename "$file")"
            ((deleted_count++))
        else
            log "WARN" "无法删除文件: $(basename "$file")"
            ((error_count++))
        fi
    done < <(find "$BACKUP_DIR" -type f -name "csa.*.sql.gz" -mtime +30 -print0 2>/dev/null)
    
    log "INFO" "备份文件清理完成: 成功删除 $deleted_count 个, 失败 $error_count 个"
}

# 清理旧日志
cleanup_old_logs() {
    log "INFO" "清理超过${MAX_LOG_DAYS}天的日志文件..."
    
    local deleted_count=0
    while IFS= read -r -d '' file; do
        if rm -f "$file"; then
            log "DEBUG" "删除日志文件: $(basename "$file")"
            ((deleted_count++))
        fi
    done < <(find "$LOG_DIR" -type f -name "backup_*.log" -mtime +${MAX_LOG_DAYS} -print0 2>/dev/null)
    
    log "INFO" "日志文件清理完成: 删除 $deleted_count 个旧日志"
}

# 检查磁盘空间
check_disk_space() {
    log "INFO" "检查磁盘空间..."
    
    local available_space=$(df "$BACKUP_DIR" | awk 'NR==2 {print $4}')
    local min_space=$((1024 * 1024))  # 至少保留1GB空间
    
    if [ "$available_space" -lt "$min_space" ]; then
        log "WARN" "磁盘空间不足,可用空间: $((available_space / 1024))MB"
        return 1
    fi
    
    local human_available=$(df -h "$BACKUP_DIR" | awk 'NR==2 {print $4}')
    log "INFO" "磁盘空间充足: $human_available 可用"
    return 0
}

# 记录系统信息
log_system_info() {
    log "DEBUG" "系统信息:"
    log "DEBUG" "  - 主机名: $(hostname)"
    log "DEBUG" "  - 当前用户: $(whoami)"
    log "DEBUG" "  - 脚本路径: $(pwd)/$(basename "$0")"
    log "DEBUG" "  - 配置文件: $CONFIG_FILE"
    log "DEBUG" "  - 备份目录: $BACKUP_DIR"
    log "DEBUG" "  - 日志文件: $LOG_FILE"
}

# 主函数
main() {
    # 检查并加载配置文件
    check_config_file
    load_config
    
    # 创建目录和设置日志文件
    create_directories
    setup_log_file
    
    # 记录开始信息
    log "INFO" "========= 开始数据库备份任务 ========="
    log "INFO" "主机: $DB_HOST:$DB_PORT, 数据库: $DB_NAME"
    
    # 记录系统信息
    log_system_info
    
    # 前置检查
    check_commands
    create_backup_dir
    check_disk_space || log "WARN" "磁盘空间紧张,但继续执行备份..."
    
    # 执行备份
    backup_database
    
    # 清理旧备份和日志
    cleanup_old_backups
    cleanup_old_logs
    
    log "INFO" "========= 数据库备份任务完成 ========="
    
    # 记录最终状态
    echo "备份完成时间: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE"
    echo "备份文件: $BACKUP_FILE" >> "$LOG_FILE"
    echo "日志文件: $LOG_FILE" >> "$LOG_FILE"
}

# 错误处理函数
error_handler() {
    local exit_code=$?
    local error_line=$1
    
    log "ERROR" "脚本执行错误 (退出码: $exit_code, 行号: $error_line)"
    log "ERROR" "备份任务失败"
    
    # 记录堆栈跟踪(如果有的话)
    if [ "$exit_code" -ne 0 ]; then
        log "DEBUG" "错误堆栈:"
        local frame=0
        while caller $frame; do
            ((frame++))
        done >> "$LOG_FILE" 2>/dev/null
    fi
}

# 设置错误陷阱
trap 'error_handler $LINENO' ERR

# 执行主函数
main "$@"

# 记录成功退出
log "INFO" "脚本正常退出"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

# 4.进阶安全

# 使用openssl加密配置文件
openssl enc -aes-256-cbc -salt -in db_config.conf -out db_config.conf.enc

# 在脚本中解密(需要提供密码)
openssl enc -aes-256-cbc -d -in db_config.conf.enc -out /tmp/db_config.conf
1
2
3
4
5