Ubuntu的Mysql设置

MySQL安装

解决密钥问题

获取并安装最新的 MySQL GPG 密钥

首先需要下载并导入 MySQL 官方最新的 GPG 签名密钥,执行以下命令:

1
wget -O - https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 | sudo gpg --dearmor -o /usr/share/keyrings/mysql.gpg

或者

1
wget -O - https://repo.mysql.com/RPM-GPG-KEY-mysql-2023 | sudo gpg --dearmor -o /usr/share/keyrings/mysql.gpg

然后需要修改 MySQL 的源列表文件(通常是/etc/apt/sources.list.d/mysql.list),将密钥引用改为新的 keyring 文件,例如将原文件中的deb https://repo.mysql.com/apt/ubuntu/ noble mysql-8.0改为:如果提示这个不能使用,那么直接删除掉,尝试使用ubuntu官方提供的软件源更新,先查看该目录下是否有mysql.list ,有就先备份

date命令的格式符语法要求+后面紧跟格式字符串(不能有空格),否则date会把%y%m%d当成额外的操作数,从而报错。

1
2
3
if [ -f /etc/apt/sources.list.d/mysql.list ]; then
sudo CP /etc/apt/sources.list.d/mysql.list /etc/apt/sources.list.d/mysql.list.bak-$(date +%y%m%d)
fi

配置 MySQL APT 仓库(若文件不存在)

  1. 创建并写入 MySQL 源配置文件(适配 Ubuntu 24.04/noble,若兼容问题则改用 22.04/jammy):
1
echo "deb [signed-by=/usr/share/keyrings/mysql.gpg] http://repo.mysql.com/apt/ubuntu/ noble mysql-8.0" | sudo tee /etc/apt/sources.list.d/mysql.list

更新 APT 缓存完成密钥导入后,执行 APT 更新命令,验证是否解决问题:

1
sudo apt update

可选)若仍有问题,检查 MySQL 仓库版本兼容性Ubuntu 24.04(Noble Numbat)是较新的版本,MySQL 的 APT 仓库可能对其支持存在延迟。如果上述步骤后仍有问题,可以考虑:

  • 暂时改用 Ubuntu 官方仓库中的 MySQL 包(Ubuntu 官方仓库提供mysql-server包,版本可能略低但兼容性更好),需要注释掉/etc/apt/sources.list.d/mysql.list中的 MySQL 官方仓库条目,然后执行sudo apt update
  • 等待 MySQL 官方更新对 Ubuntu 24.04 的仓库支持,或改用 MySQL 的通用二进制包安装。
  • Ubuntu 22.04 及以上版本推荐使用signed-by参数指定密钥文件,而非apt-keyapt-key已被标记为弃用),这样更安全且符合新的 APT 规范。

执行完上述步骤后,再次运行sudo apt update,应该可以正常验证 MySQL 仓库的签名,消除该错误提示。

检查 MySQL 仓库的兼容性

Ubuntu 24.04(noble)是较新的版本,MySQL 官方的 APT 仓库可能尚未完全适配该版本。可尝试将仓库的版本代号改为 Ubuntu 22.04(jammy,MySQL 对其支持更成熟),修改mysql.list

1
sudo sed -i 's/noble/jammy/' /etc/apt/sources.list.d/mysql.list

修改后执行sudo apt update,验证是否仍有密钥错误(注:此方法为临时兼容方案,若 MySQL 后续发布 noble 版本,需改回)。

1
2
3
4
sudo apt clean
sudo rm -rf /var/lib/apt/lists/*repo.mysql.com*
sudo apt update
sudo apt install mysql-server 已经安装,就不需要安装了

增强密钥信任级别(复制到 APT 信任目录):

1
sudo cp /usr/share/keyrings/mysql.gpg /etc/apt/trusted.gpg.d/mysql.gpg

卸载MySQL

如果你使用的是Ubuntu的默认MySQL版本(如MySQL 5.7或更高版本),可以通过apt包管理器来卸载,别的版本请使用搜索工具。

停止MySQL服务:

1
sudo systemctl stop mysql

卸载MySQL

1
sudo apt-get remove --purge mysql-server mysql-client mysql-common mysql-server-core-* mysql-client-core-*

清理残留配置文件:

1
2
sudo apt-get autoremove	\
sudo apt-get autoclean

Ubuntu卸载mysql-apt-config_0.8.32-1_all.deb

在Ubuntu系统中,如果你想要卸载mysql-apt-config包,可以使用以下步骤。mysql-apt-config是一个工具,用于帮助配置MySQL的APT仓库,以便安装和更新MySQL服务器和客户端软件包。

更新包列表

在卸载任何包之前,建议先更新你的包列表,以确保你正在操作的软件包是最新的。使用以下命令:

1
sudo apt update

卸载mysql-apt-config

接下来,使用apt-get命令来卸载mysql-apt-config。执行以下命令:

1
sudo apt-get remove mysql-apt-config

这条命令会卸载mysql-apt-config及其依赖,但不删除配置文件。

Ubuntu导入数据到mysql

登录MySQL

使用以下命令登录MySQL:

1
mysql -u root -p

输入你之前设置的root用户密码。

创建数据库和用户(如果需要)

在导入数据之前,你可能需要创建一个数据库和用户:因为数据库不包含之前的用户信息,所以数据中如果没有用户,需要创建一个用户才能导入,如果有用户直接导入到指定用户信息中

1
2
3
4
5
CREATE DATABASE mydatabase;
CREATE USER 'myuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON mydatabase.* TO 'myuser'@'localhost';
FLUSH PRIVILEGES;
EXIT

mydatabase:数据库名字

myuser:你要创建的用户名称

localhost:你的主机名称,可以是IP也可以是别的,也可以不填写,直接修改成如下格式:

1
CREATE USER 'myuser' IDENTIFIED BY 'password';

password:这个数据库的密码

导入数据

使用命令行导入数据:

假设你的数据文件是.sql格式,你可以使用以下命令导入数据:

1
mysql -u myuser -p mydatabase < /path/to/your/datafile.sql

输入用户的密码。确保将mydatabase、myuser、/path/to/your/datafile.sql替换为实际的数据库名、用户名和文件路径。

myuser:用户名

mydatabase:待导入的数据

Ubuntumysql导出指定的数据库

Ubuntumysql自动备份数据库

在Ubuntu上定时备份MySQL数据库并自动删除旧的备份文件,你可以使用cron定时任务结合mysqldump命令来完成。下面我将详细介绍如何设置这个过程。

创建备份目录

创建一个目录用于存放备份文件,例如/backup/mysql

1
sudo mkdir -p /backup/mysql

创建备份脚本

创建一个脚本文件,例如backup.sh,用于执行数据库备份。

1
sudo nano /usr/local/bin/backup.sh

在打开的编辑器中,输入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

# MySQL数据库信息
DB_NAME="your_database_name"
DB_USER="your_username"
DB_PASS="your_password"
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M)
BACKUP_FILE="$DB_NAME-$DATE.sql"

# 创建备份文件
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_DIR/$BACKUP_FILE

# 删除7天前的备份文件(可根据需要调整天数)
find $BACKUP_DIR -type f -name "*.sql" -mtime +7 -exec rm {} \;

根据你的需求调整find命令中的-mtime +7部分,以控制保留备份的天数。例如,如果你希望保留30天的备份,则使用-mtime +30。

your_database_name: 数据库名称

your_username:数据库的用户名称

your_password:数据库密码

保存并关闭文件,然后使其可执行:

1
sudo chmod +x /usr/local/bin/backup.sh

设置Cron定时任务

编辑crontab文件来设置定时任务:

1
crontab -e

在打开的编辑器中,添加以下行来每天凌晨1点执行备份脚本:

1
0 1 * * * /usr/local/bin/backup.sh

检查/backup/mysql目录,确认备份文件是否正确生成并被正确删除。

注意:
确保将your_database_name, your_username, 和 your_password替换为实际的数据库名、用户名和密码。出于安全考虑,避免在脚本中直接使用密码,可以考虑使用.my.cnf文件或其他安全措施来管理MySQL凭证。例如,你可以在用户的家目录下创建.my.cnf文件,并在其中存储登录凭证。然后在脚本中使用–defaults-file=/path/to/.my.cnf选项来引用它。配置如下,只需要修改/usr/local/bin/backup.sh改文件

脚本用户名和密码使用–defaults-file=/path/to/.my.cnf,如何配置

创建.my.cnf文件

1
sudo nano /etc/mysql/backup.cnf

配置文件内容

1
2
3
4
[client]
user = your_username
password = your_password
host = localhost #如果在创建用户时候,没有创建主机名,这一行可以不填写,

替换your_username为实际用户名、your_password为实际密码,文件权限需设置为600‌

修改备份脚本

‌调整backup.sh脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

# MySQL数据库信息
DB_NAME="your_database_name"
DEFAULTS_FILE="/etc/mysql/backup.cnf"
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M)
BACKUP_FILE="$DB_NAME-$DATE.sql"

# 创建备份文件,如果没有配置主机名,还需要添加这个参数 --no-tablespaces
mysqldump --defaults-file=$DEFAULTS_FILE --no-tablespaces $DB_NAME > $BACKUP_DIR/$BACKUP_FILE

# 删除7天前的备份文件(可根据需要调整天数)
find $BACKUP_DIR -type f -name "${DB_NAME}-*.sql" -mtime +7 -exec rm {} \;

错误问题

文件格式或解释器路径错误

修复行尾符问题‌
**若脚本在 Windows 中编辑后上传至 Linux,需转换 CRLF 为 LF 格式:

1
sed -i 's/\r$//' /etc/mysql/backup.cnf

远程连接mysql

SSH端口映射,建立隧道服务

这里是服务器端的创建

创建专属 SSH 用户

建议创建一个仅用于 MySQL 隧道的专用用户(避免用 root):

1
2
3
4
5
6
7
8
9
10
# 创建用户(无登录Shell,仅用于隧道)
useradd -m -s /usr/sbin/nologin mysql_tunnel

# 设置用户SSH密钥(本地生成密钥对,将公钥上传到该用户)
mkdir -p /home/mysql_tunnel/.ssh
chmod 700 /home/mysql_tunnel/.ssh
# 将本地生成的公钥(id_rsa.pub)内容写入authorized_keys
vim /home/mysql_tunnel/.ssh/authorized_keys
chmod 600 /home/mysql_tunnel/.ssh/authorized_keys
chown -R mysql_tunnel:mysql_tunnel /home/mysql_tunnel/.ssh
命令片段 含义(大白话)
useradd Ubuntu 中创建新用户的核心命令(区别于 adduser,是更底层的非交互式命令)。
-m 自动创建该用户的家目录(路径为 /home/mysql_tunnel),不加此参数则不创建家目录。
-s /usr/sbin/nologin 指定该用户的默认登录 Shell 为 nologin核心作用是禁止该用户登录系统
mysql_tunnel 要创建的用户名(自定义,这里用于和 MySQL 隧道相关的用途)。

usermod 命令修改(推荐,最简单)

这是修改已有用户 Shell 的标准命令,无需手动编辑配置文件。

基础命令(禁止指定用户登录)

1
sudo usermod -s /usr/sbin/nologin 用户名

-sshell 的缩写,用于指定用户的默认登录 Shell;

/usr/sbin/nologin:系统内置的 “无登录 Shell”,尝试登录会提示 This account is currently not available.

/bin/false 禁止登录(更严格)

/bin/falsenologin 更严格,尝试登录时无任何提示,直接退出:

1
sudo usermod -s /bin/false 用户名

验证修改是否生效

执行以下命令,查看用户的 Shell 配置:

1
cat /etc/passwd | grep 用户名

输出示例(修改成功):

1
mysql_tunnel:x:1001:1001::/home/mysql_tunnel:/usr/sbin/nologin

解除用户登录到系统

1
sudo usermod -s /bin/bash 用户名

服务器sshd配置

需要先安装openssh-server

1
2
3
4
5
6
# 安装(若未安装)
sudo apt update && sudo apt install -y openssh-server

# 确认sshd运行
sudo systemctl enable --now ssh
sudo systemctl status ssh

其他的配置在基础配置中配置了。

在服务器端的/etc/ssh/sshd_config.d目录添加mysqltunel.conf内容如下

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
Port 2222        # 新增MySQL隧道专属端口

# ========== 2222端口专属限制(核心) ==========
Match LocalPort 2222
# 强制密钥登录,禁用所有密码相关认证
# 强制密钥登录,禁用所有密码相关认证
PasswordAuthentication no
PubkeyAuthentication yes
# 再次关闭挑战 - 响应认证
ChallengeResponseAuthentication no
# 仅允许TCP端口转发(禁止Shell/TTY/X11)
AllowTcpForwarding yes
# 禁止分配 TTY(终端)杜绝通过 2222 端口获取交互式命令行,只能用隧道,不能登录操作
PermitTTY no
# 再次关闭 X11 转发
X11Forwarding no
# 允许建立隧道(端口转发)
PermitTunnel yes
# 超时配置(避免空闲隧道占用)
# 每 30 秒向客户端发送一次 “存活检测”
ClientAliveInterval 30
# 累计 10 次检测不到客户端响应就断开连接
ClientAliveCountMax 10
# 仅允许mysql_tunnel用户使用该端口(严格限制)
AllowUsers mysql_tunnel

重启 sshd 并验证端口

1
2
3
4
5
6
7
8
9
10
# 检查配置语法(无报错则正常)
sudo sshd -t

# 重启sshd
sudo systemctl restart ssh

# 验证2222端口监听(应看到0.0.0.0:2222)
sudo ss -tulpn | grep sshd
如果没有看到建议重启
shutdown -r now

配置专用用户的 SSH 密钥

本地生成 SSH 密钥对(本地终端执行)

1
2
3
4
5
6
7
# 生成专用密钥(无密码,或加-N "你的密钥密码"更安全)
ssh-keygen -t ed25519 -b 4096 -f ~/.ssh/mysql_tunnel_key -N ""

# 密钥权限(必须严格,否则sshd拒绝)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/mysql_tunnel_key
chmod 644 ~/.ssh/mysql_tunnel_key.pub

将公钥上传到远端 mysql_tunnel 用户

1
2
3
4
5
6
7
8
# 本地执行(替换为远端服务器IP)
ssh-copy-id -i ~/.ssh/mysql_tunnel_key.pub -p 22 mysql_tunnel@远端服务器IP
#还可以直接拷贝这个数据到服务器端

# 验证远端权限(远端执行)
sudo chown -R mysql_tunnel:mysql_tunnel /home/mysql_tunnel/.ssh
sudo chmod 700 /home/mysql_tunnel/.ssh
sudo chmod 600 /home/mysql_tunnel/.ssh/authorized_keys

防火墙放行 2222 端口(Ubuntu 24.04 默认用 ufw)

1
2
3
4
5
6
7
8
9
# 放行2222端口(仅允许TCP)
sudo ufw allow 2222/tcp comment 'MySQL SSH Tunnel'


# 重启ufw
sudo ufw reload

# 验证规则
sudo ufw status

如果知道具体的客户端连接,那么就可以修改mysqltunel.confAllowUsers mysql_tunnel@客户端IP地址;

ufw中删除sudo ufw delete allow 2222/tcp,然后添加sudo ufw allow from 客户端IP地址 to any port 2222

这些操作后,重新启动ufwssh;或者shutdown -r now

允许一段 IP(比如内网 192.168.1.0/24)

1
sudo ufw allow from 192.168.1.0/24 to any port 2222

ssh隧道连接

客户端安装mysql

本地机器需要安装 MySQL 客户端

先更新软件源

安装 MySQL 客户端(两种方式,选其一即可)

方式 1:安装官方精简版客户端(推荐,体积小)
1
sudo apt install -y mysql-client

仅包含 mysql 命令行客户端、mysqldump 等核心工具,无多余组件,适合仅做连接的场景;

安装完成后直接可用 mysql 命令。

方式 2:安装完整客户端套件(包含更多工具)

如果后续需要用到 mysqldumpmysqladmin 等工具,可安装完整套件:

1
sudo apt install -y mysql-client-core-8.0
  • Ubuntu 24.04 默认自带 MySQL 8.0 版本,该包是 8.0 系列的核心客户端,兼容绝大多数 MySQL 版本(5.7/8.0 都可连接)。
验证安装是否成功
1
2
# 查看 mysql 命令是否可用
mysql --version

输出示例(证明安装成功):

1
mysql  Ver 8.0.36-0ubuntu0.24.04.1 for Linux on x86_64 ((Ubuntu))

建立隧道

切换用户

1
su mysql_tunnel

本地配置(Ubuntu 24.04)- 自动映射端口

测试手动建立隧道(验证连通性)
1
2
3
4
5
6
7
8
9
10
11
12
# 本地执行(后台运行,仅端口转发)
ssh -f -N \
-i ~/.ssh/mysql_tunnel_key \
-L 33060:127.0.0.1:3306 \
-p 2222 \
mysql_tunnel@远端服务器IP

# 验证隧道进程(应看到ssh进程)
ps aux | grep mysql_tunnel_key

# 测试连接MySQL(本地执行)
mysql -u 远端MySQL用户名 -p --host=127.0.0.1 --port=33060

参数说明

在本地后台启动一个 SSH 隧道,将本地 33060 端口的请求,通过 2222 端口转发到远端服务器的 3306 端口(MySQL 端口),且仅做端口转发、不建立交互式 Shell,专门用于 MySQL 远程访问。

参数 / 片段 完整写法 含义(大白话) 作用 / 使用场景
ssh - SSH 客户端核心命令 用于建立 SSH 连接 / 端口转发 / 隧道
-f --fork 后台运行(fork 到后台) 执行命令后不占用当前终端,直接回到命令提示符,隧道在后台运行
-N --no-command 不执行远程命令 仅建立 SSH 连接做端口转发,不执行任何远程 Shell 命令(核心!避免误操作)
-i ~/.ssh/mysql_tunnel_key --identity-file=PATH 指定登录用的私钥文件 不用系统默认的 id_rsa/id_ed25519,而是用 mysql_tunnel_key 这个专用密钥,适配你之前的 mysql_tunnel 用户密钥认证
-L 33060:127.0.0.1:3306 --local-port=LPORT:HOST:RPORT 本地端口转发(核心) 格式:本地端口:目标主机:目标端口 含义:把本地 33060 端口的请求,转发到「远端服务器上的 127.0.0.1:3306」(即远端 MySQL 端口)
-p 2222 --port=PORT 指定远端 SSH 服务端口 不连默认的 22 端口,而是连你配置的 2222 端口(MySQL 隧道专属端口)
mysql_tunnel@远端服务器IP - 指定登录的用户 + 服务器地址 mysql_tunnel 用户(你配置的专用隧道用户)登录远端服务器
关键参数的深度说明(补充函数 / 扩展参数)
核心转发参数(-L/-R/-D)—— SSH 隧道的三种模式

你用的 -L本地端口转发(最常用),补充另外两种模式,方便你理解全貌:

参数 模式 核心作用 适用场景
-L [本地IP:]本地端口:目标IP:目标端口 本地转发(Local) 本地端口 → SSH 服务器 → 目标端口 访问远端服务器内网服务(如你访问远端 MySQL)
-R [远端IP:]远端端口:目标IP:目标端口 远程转发(Remote) 远端端口 → SSH 服务器 → 本地端口 让外网访问本地内网服务(如本地服务暴露到远端)
-D [本地IP:]本地端口 动态转发(Dynamic) 本地端口作为 SOCKS 代理 全局代理(如翻墙、多服务转发)
后台 / 无命令参数(-f/-N/-q)—— 隧道专用优化
参数 补充说明 扩展用法
-f 后台运行,但会先要求输入密钥密码(如果密钥有密码) 搭配 -N 使用,纯端口转发场景必加
-N 仅建立连接,不执行任何远程命令 避免误执行 Shell 命令,隧道场景必加
-q 静默模式(Quiet) 减少输出日志,后台运行更干净,可加在命令中:ssh -f -N -q ...
密钥 / 认证参数(-i/-o)—— 安全加固
参数 补充说明 扩展参数
-i 指定私钥文件,优先级高于默认密钥 可加多个 -i 指定多密钥(如 -i key1 -i key2),SSH 会依次尝试
-o StrictHostKeyChecking=no 跳过主机密钥验证(慎用) 自动化脚本中常用,但有中间人攻击风险,生产环境不推荐
-o UserKnownHostsFile=/dev/null 不保存服务器公钥到 known_hosts 临时隧道使用,避免污染本地 known_hosts
连接稳定性参数(-o ServerAliveInterval)—— 防止隧道断开

你之前配置了 SSH 服务端的 ClientAliveInterval,客户端也可加对应参数保障连接:

1
2
3
4
5
6
7
8
# 客户端每30秒发一次心跳,避免被服务端断开
ssh -f -N \
-i ~/.ssh/mysql_tunnel_key \
-L 33060:127.0.0.1:3306 \
-p 2222 \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=10 \
mysql_tunnel@远端服务器IP

ServerAliveInterval=30:客户端每 30 秒向服务端发心跳;

ServerAliveCountMax=10:10 次心跳无响应则断开(和服务端配置呼应)。

稳定版(加保活 + 超时,生产推荐)
1
2
3
4
5
6
7
8
ssh -f -N -q \
-i ~/.ssh/mysql_tunnel_key \
-L 33060:127.0.0.1:3306 \
-p 2222 \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=10 \
-o ConnectTimeout=10 \
mysql_tunnel@192.168.100.100

验证隧道是否生效

1
2
3
4
5
# 1. 查看本地33060端口是否被占用(有输出则生效)
netstat -tulpn | grep 33060

# 2. 测试连接远端MySQL(本地需装mysql-client)
mysql -u 远端MySQL用户名 -p --host=127.0.0.1 --port=33060

ssh隧道连接意外断开

手动重连(临时应急,简单直接)

步骤1终止旧隧道进程
1
2
3
4
5
6
# 查找隧道PID并杀掉(过滤掉grep临时进程)
PID=$(ps aux | grep "33060:127.0.0.1:3306" | grep -v grep | awk '{print $2}')
if [ -n "$PID" ]; then
kill -9 $PID
echo "旧隧道进程 $PID 已终止"
fi
步骤2重新启动隧道
1
2
3
4
5
6
7
8
9
10
11
# 执行稳定版隧道命令
ssh -f -N -q \
-i ~/.ssh/mysql_tunnel_key \
-L 33060:127.0.0.1:3306 \
-p 2222 \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=10 \
-o ConnectTimeout=10 \
mysql_tunnel@192.168.100.100

echo "新隧道已启动,可访问 127.0.0.1:33060 连接远端MySQL"

自动重连(生产推荐,无需手动干预)

写一个监控脚本,自动检测隧道状态,服务器恢复后自动重建隧道:

步骤 1:创建自动重连脚本(保存为 mysql_tunnel_keepalive.sh
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
#!/bin/bash
# 配置项(根据实际情况修改)
SSH_KEY="$HOME/.ssh/mysql_tunnel_key" # 私钥路径
LOCAL_PORT="33060" # 本地转发端口
REMOTE_SSH_PORT="2222" # 远端SSH端口
REMOTE_SERVER="192.168.100.100" # 远端服务器IP
SSH_USER="mysql_tunnel" # 远端登录用户
TARGET="127.0.0.1:3306" # 远端MySQL地址+端口

# 隧道启动命令
TUNNEL_CMD="ssh -f -N -q \
-i $SSH_KEY \
-L $LOCAL_PORT:$TARGET \
-p $REMOTE_SSH_PORT \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=10 \
-o ConnectTimeout=10 \
$SSH_USER@$REMOTE_SERVER"

# 循环监控并重启隧道
while true; do
# 检查隧道是否存活(通过本地端口是否被占用判断)
netstat -tulpn | grep ":$LOCAL_PORT " | grep -v grep > /dev/null
if [ $? -ne 0 ]; then
# 杀掉残留进程
PID=$(ps aux | grep "$LOCAL_PORT:$TARGET" | grep -v grep | awk '{print $2}')
[ -n "$PID" ] && kill -9 $PID > /dev/null 2>&1

# 重启隧道
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 隧道断开,正在重连..."
$TUNNEL_CMD
if [ $? -eq 0 ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 隧道重连成功!"
else
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 隧道重连失败,10秒后重试..."
fi
fi
sleep 10 # 每10秒检查一次
done
赋予权限并后台运行
1
2
3
4
5
6
7
8
# 赋予执行权限
chmod +x mysql_tunnel_keepalive.sh

# 后台运行(日志输出到 tunnel.log,终端关闭不影响)
nohup ./mysql_tunnel_keepalive.sh > /var/log/mysql_tunnel.log 2>&1 &

# 查看脚本运行状态
ps aux | grep mysql_tunnel_keepalive.sh | grep -v grep

服务器断开 5 分钟恢复后,脚本会在 10 秒内检测到隧道断开,自动重建连接,你无需手动操作,本地访问 127.0.0.1:33060 即可立即恢复 MySQL 连接。

脚本日志查看:实时查看重连状态

1
tail -f /var/log/mysql_tunnel.log

停止自动重连脚本

1
2
PID=$(ps aux | grep mysql_tunnel_keepalive.sh | grep -v grep | awk '{print $2}')
kill -9 $PID

优化后的完整脚本(带优雅停止模式)

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
#!/bin/bash
# 配置项(根据实际情况修改)
SSH_KEY="$HOME/.ssh/mysql_tunnel_key" # 私钥路径
LOCAL_PORT="33060" # 本地转发端口
REMOTE_SSH_PORT="2222" # 远端SSH端口
REMOTE_SERVER="192.168.100.100" # 远端服务器IP
SSH_USER="mysql_tunnel" # 远端登录用户
TARGET="127.0.0.1:3306" # 远端MySQL地址+端口
STOP_FLAG_FILE="/tmp/stop_mysql_tunnel" # 停止标记文件
SCRIPT_PID_FILE="/tmp/mysql_tunnel.pid" # 脚本PID文件

# 隧道启动命令
TUNNEL_CMD="ssh -f -N -q \
-i $SSH_KEY \
-L $LOCAL_PORT:$TARGET \
-p $REMOTE_SSH_PORT \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=10 \
-o ConnectTimeout=10 \
$SSH_USER@$REMOTE_SERVER"

# ==================== 核心功能函数 ====================
# 1. 停止脚本+清理隧道进程
stop_tunnel() {
echo -e "\n[$(date +'%Y-%m-%d %H:%M:%S')] 开始停止隧道和监控脚本..."

# 杀掉隧道进程
PID=$(ps aux | grep "$LOCAL_PORT:$TARGET" | grep -v grep | awk '{print $2}')
if [ -n "$PID" ]; then
kill -9 $PID > /dev/null 2>&1
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 隧道进程 $PID 已终止"
fi

# 清理标记文件和PID文件
[ -f "$STOP_FLAG_FILE" ] && rm -f "$STOP_FLAG_FILE"
[ -f "$SCRIPT_PID_FILE" ] && rm -f "$SCRIPT_PID_FILE"

echo "[$(date +'%Y-%m-%d %H:%M:%S')] 脚本已优雅停止!"
exit 0
}

# 2. 捕获终止信号(Ctrl+C、kill 等)
trap stop_tunnel SIGINT SIGTERM SIGQUIT

# ==================== 脚本入口逻辑 ====================
# 支持传 "stop" 参数直接停止
if [ "$1" = "stop" ]; then
stop_tunnel
fi

# 保存脚本PID到文件(方便后续操作)
echo $$ > "$SCRIPT_PID_FILE"
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 隧道监控脚本启动,PID: $(cat $SCRIPT_PID_FILE)"
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 停止方式1:按 Ctrl+C 优雅停止"
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 停止方式2:执行 $0 stop"
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 停止方式3:创建文件 touch $STOP_FLAG_FILE"

# 循环监控并重启隧道(带停止判断)
while true; do
# 判断是否需要停止(标记文件存在则停止)
if [ -f "$STOP_FLAG_FILE" ]; then
stop_tunnel
fi

# 检查隧道是否存活(通过本地端口是否被占用判断)
netstat -tulpn | grep ":$LOCAL_PORT " | grep -v grep > /dev/null
if [ $? -ne 0 ]; then
# 杀掉残留进程
PID=$(ps aux | grep "$LOCAL_PORT:$TARGET" | grep -v grep | awk '{print $2}')
[ -n "$PID" ] && kill -9 $PID > /dev/null 2>&1

# 重启隧道
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 隧道断开,正在重连..."
$TUNNEL_CMD
if [ $? -eq 0 ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 隧道重连成功!"
else
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 隧道重连失败,10秒后重试..."
fi
fi

sleep 10 # 每10秒检查一次
done

隧道连接第二种方法

配置系统服务(开机自动建立隧道)

创建 systemd 服务文件

1
sudo vim /etc/systemd/system/mysql-ssh-tunnel.service

写入以下内容(替换<你的本地用户名>/<远端服务器IP>):

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
#  [Unit] 段:服务元信息与依赖
[Unit]
# 服务的描述信息,方便识别这个服务的用途(远程 MySQL 的自动 SSH 隧道)
Description=Auto SSH Tunnel for Remote MySQL
# 定义服务启动时机:必须等network.target(网络基础服务)和network-online.target(网络完全可用)启动完成后,才启动本服务
After=network.target network-online.target
#弱依赖:启动本服务时会尝试启动network-online.target,但即使后者启动失败,本服务仍会尝试启动(保证网络就绪后再连隧道)
Wants=network-online.target
# 限制1分钟内最多重启5次,避免无意义循环
# StartLimitIntervalSec=60
# StartLimitBurst=5

# [Service] 段:服务核心运行规则
[Service]
# 替换为你的本地用户名(如ubuntu、root)
# 指定服务以哪个用户 / 用户组运行(避免用 root,提升安全性)
User=<你的本地用户名>
Group=<你的本地用户名>
# 服务类型:表示ExecStart指定的命令是服务的主进程,systemd 会直接启动该进程并视为服务启动完成(最常用的类型)
Type=simple
# 核心命令(替换远端服务器IP)
ExecStart=/usr/bin/ssh -N \
-i /home/<你的本地用户名>/.ssh/mysql_tunnel_key \
-L 33060:127.0.0.1:3306 \
-p 2222 \
-o ServerAliveInterval=10 \
-o ServerAliveCountMax=3 \
-o ConnectTimeout=5 \
-o TCPKeepAlive=yes \
-o BatchMode=yes \
-o LogLevel=ERROR \
-o StrictHostKeyChecking=accept-new \
mysql_tunnel@<远端服务器IP>
# 异常自动重启
# 重启规则:无论服务以何种原因退出(正常 / 异常),都会自动重启(核心的自动重连配置)
Restart=always
# 重启间隔:服务退出后,等待 10 秒再尝试重启
RestartSec=10
# 断连后5秒重启(默认5秒,缩短重启间隔)
TimeoutStopSec=5

# 停止超时5秒 进程守护:确保SSH进程被正确监控
KillMode=process
# 关键:删除 RestartPreventExitStatus=255(允许255退出码触发重启) 补充:标记常见退出码为正常,避免触发启动限制
SuccessExitStatus=0 1 255


# [Install] 段:服务安装配置
[Install]
WantedBy=multi-user.target
1
2
systemctl daemon-reload

MySQL 命令

查看 MySQL 服务器上的所有数据库

MySQL 服务里有哪些数据库可以操作:

1
2
-- 查看 MySQL 服务器中所有的数据库(无需选中任何数据库即可执行)
SHOW DATABASES;

说明:执行后会列出系统自带的数据库(如 mysqlinformation_schemaperformance_schema)和你自己创建的业务数据库(如 test_dbshop_db)。

查看指定数据库中的所有数据表

先选中目标数据库,再查看该库下的表,这是衔接 “数据库” 和 “数据表” 的关键步骤:

1
2
3
4
5
6
7
8
-- 1. 选中要查看的数据库(替换为你要查看的数据库名)
USE 你的数据库名;

-- 2. 查看该数据库下的所有数据表
SHOW TABLES;

-- 【扩展】如果不想先执行 USE,也可以直接指定数据库查看表
SHOW TABLES FROM 你的数据库名;

查看数据表的具体内容

这一步和之前讲的一致,但补充 “跨库查看表内容” 的写法,让操作更灵活:

基础查看(选中数据库后)

1
2
3
4
5
6
7
8
9
10
11
-- 查看表中所有数据(小表适用)
SELECT * FROM 你的表名;

-- 查看前 N 行数据(大表必用,避免资源占用)
SELECT * FROM 你的表名 LIMIT 10;

-- 查看指定列的数据(效率更高)
SELECT 列名1, 列名2 FROM 你的表名;

-- 带条件筛选数据
SELECT * FROM 你的表名 WHERE 条件; -- 例:WHERE age > 18

跨库查看表内容(无需先执行 USE)

如果不想切换数据库,可直接通过 数据库名.表名 的方式访问:

1
2
-- 查看 test_db 数据库中 user 表的前 5 行数据
SELECT * FROM test_db.user LIMIT 5;

完整操作示例(从查库到查数据)

假设你想查看 MySQL 里的所有数据库,然后查看 shop_db 库的表,再看 goods 表的内容,完整流程:

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
-- 1. 登录 MySQL(终端执行)
mysql -u root -p

-- 2. 查看服务器上所有数据库
SHOW DATABASES;
-- 输出示例:mysql, information_schema, test_db, shop_db

-- 3. 查看 shop_db 库中的所有表(两种方式任选)
-- 方式1:先选中数据库,再查表
USE shop_db;
SHOW TABLES;
-- 输出示例:goods, order, user

-- 方式2:直接查表(不切换库)
SHOW TABLES FROM shop_db;

-- 4. 查看 goods 表的结构(了解字段信息)
DESC shop_db.goods; -- 或选中库后写 DESC goods;

-- 5. 查看 goods 表的内容
-- 选中库后查看:
SELECT goods_name, price FROM goods WHERE price < 100 LIMIT 20;

-- 不选中库直接查看:
SELECT goods_name, price FROM shop_db.goods WHERE price < 100 LIMIT 20;