【项目学习】在MacBook Air M2上搭建TinyWebServer环境

最近打算通过TinyWebServer这个项目学习一下cpp。由于手头只有一台MacBook Air M2,项目的环境是Ubuntu.因此通过安装虚拟机来运行项目。但是由于M2时Arm架构,并且Ubuntu上没有项目对应的MySQ5.7版本,只能通过源码编译安装MySQL,过程比较崎岖。记录一下这个过程。

一、准备工作

  • 安装ubuntu22.04虚拟机

    • 注意,磁盘分配至少35GB

    • 安装包vim,ssh,ping,net-tools

    • ssh登录,允许root登录

    • 换源

  • 编译安装mysql5.7

    • boost问题(修改编译时boost路径)
    • openssl版本太高(手动编译安装)
    • 磁盘空间不够(重新安装虚拟机)
  • 运行mysql

    • 初始化mysql
    • 创建systemd服务,修改MySQL密码
    • 创建数据库

1. 虚拟机安装

参考链接

安装虚拟机需要做的

  • 安装包vim, ssh,ping,net-tools
  • ssh登录,允许root登录
  • 换源
sudo apt install iputils-ping
sudo apt-get update
sudo apt-get install openssh-server
sudo apt install vim
sudo apt install make
sudo apt install net-tools

换源

vim /etc/apt/sources.list

添加以下内容:

# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-security main restricted universe multiverse

# 预发布软件源,不建议启用
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse

2. 编译安装MySQL5.7

参考链接

tar -xzf mysql-boost-5.7.44.tar.gz
mkdir build
cd build

# 安装一些依赖包
sudo apt update
sudo apt install cmake build-essential libncurses5-dev libaio-dev libssl-dev libedit-dev libreadline-dev zlib1g-dev libcurl4-openssl-dev libevent-dev libgoogle-perftools-dev libjemalloc-dev

配置编译参数
cmake .. \
  -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
  -DWITH_BOOST=boost \
  -DWITH_SSL=yes \
  -DWITH_ZLIB=bundled \
  -DWITH_EDITLINE=bundled \
  -DWITH_CURL=yes \
  -DWITH_JEMALLOC=bundled \
  -DWITH_SYSTEMD=1 \
  -DCMAKE_C_FLAGS="-march=armv8-a" \
  -DCMAKE_CXX_FLAGS="-march=armv8-a"

可能需要的操作
// cmake寻找依赖的包
sudo apt install pkg-config
export PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig
pkg-config --modversion openssl

// 安装openssl包
sudo apt update
sudo apt install libssl-dev
sudo apt install --reinstall libssl-dev openssl


报错1:找不到boost库

CMake Error at cmake/boost.cmake:88 (MESSAGE):
  You can download it with -DDOWNLOAD_BOOST=1 -DWITH_BOOST=<directory>

  This CMake script will look for boost in <directory>.  If it is not there,
  it will download and unpack it (in that directory) for you.

  If you are inside a firewall, you may need to use an http proxy:

  export http_proxy=http://example.com:80

Call Stack (most recent call first):
  cmake/boost.cmake:174 (COULD_NOT_FIND_BOOST)
  CMakeLists.txt:547 (INCLUDE)

解决:下载的是带有boost版本的源码,但是博客中的cmake参数找不到boost。改一下指定路径。

将boost的路径改为-DWITH_BOOST=$(pwd)/../boost/boost_1_59_0.最终的编译参数如下:

cmake .. \
  -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
  -DWITH_BOOST=$(pwd)/../boost/boost_1_59_0
  -DWITH_SSL=yes \
  -DWITH_ZLIB=bundled \
  -DWITH_EDITLINE=bundled \
  -DWITH_CURL=yes \
  -DWITH_JEMALLOC=bundled \
  -DWITH_SYSTEMD=1 \
  -DCMAKE_C_FLAGS="-march=armv8-a" \
  -DCMAKE_CXX_FLAGS="-march=armv8-a"

报错2:找不到合适的 openssl包(安装步骤在最下面).

CMake Error at cmake/ssl.cmake:63 (MESSAGE):
  Please install the appropriate openssl developer package.

Call Stack (most recent call first):
  cmake/ssl.cmake:264 (FATAL_SSL_NOT_FOUND_ERROR)
  CMakeLists.txt:579 (MYSQL_CHECK_SSL)

解决:手动安装openssl,并将cmake编译选项改成如下设置。

cmake .. \
  -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
  -DWITH_BOOST=$(pwd)/../boost/boost_1_59_0 \
  -DWITH_SSL=/usr/local/openssl \
  -DWITH_ZLIB=bundled \
  -DWITH_EDITLINE=bundled \
  -DWITH_CURL=yes \
  -DWITH_JEMALLOC=bundled \
  -DWITH_SYSTEMD=1 \
  -DCMAKE_C_FLAGS="-march=armv8-a" \
  -DCMAKE_CXX_FLAGS="-march=armv8-a"

3. 初始化MySQL

创建 MySQL 用户和组,创建一个专用的 MySQL 用户和组:

sudo groupadd mysql
sudo useradd -r -g mysql mysql

初始化数据目录,初始化 MySQL 数据目录:

cd /usr/local/mysql
sudo bin/mysqld --initialize --user=mysql	# 注意,执行完这一步后会生成一个临时密码,要记录这个密码用于初始登录mysql。否则需要通过其他操作修改密码。

设置权限,设置 MySQL 目录的权限:

sudo chown -R mysql:mysql /usr/local/mysql
sudo chown -R mysql:mysql /usr/local/mysql/data

创建Mysql配置文件,在/etc/目录下创建my.cnf并保存,配置文件内容如下:

vim /etc/my.cnf

[mysqld]
# 基本配置
# skip-grant-tables	# 免密登录
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
socket = /tmp/mysql.sock
port = 3306
pid-file = /usr/local/mysql/data/mysqld.pid
 
# 日志配置
log-error = /usr/local/mysql/data/error.log
slow-query-log = 1
slow-query-log-file = /usr/local/mysql/data/slow-query.log
 
# InnoDB 配置
innodb_data_home_dir = /usr/local/mysql/data
innodb_log_group_home_dir = /usr/local/mysql/data
innodb_buffer_pool_size = 8024M
innodb_log_file_size = 100M
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = 1
 
 
# 其他配置
max_connections = 151
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
key_buffer_size = 16M
 
#bind-address = 0.0.0.0

4. 创建systemd服务

在基于 systemd 的 Linux 系统(例如Ubuntu 16.04 及以上版本)中,可以通过创建一个专门的服务文件来配置和管理 MySQL 服务器的启动、停止等操作。

systemd:

  • Linux 的一种初始化系统和服务管理器,用于启动系统、加载服务、以及管理服务的生命周期。
  • 提供 systemctl 命令来控制服务(如启动、停止、重启等)。

systemd 服务文件:

  • 一个以 .service 结尾的配置文件,定义某个服务的行为(如启动命令、依赖项、日志路径等)。
  • 通常存放在 /etc/systemd/system/ 目录中。

为什么需要创建服务文件?

  • 手动安装MySQL(如从源码编译或非标准包安装),没有自动创建相应的 mysqld 服务文件。为了通过 systemctl 命令管理 MySQL,需要手动创建一个服务文件,告知系统如何启动 MySQL。

创建一个 systemd 服务文件来管理 MySQL 服务。创建文件 /etc/systemd/system/mysqld.service,内容如下

vim /etc/systemd/system/mysqld.service

[Unit]
Description=MySQL Server
After=network.target
 
[Service]
User=mysql
Group=mysql
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -SIGINT $MAINPID
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --pid-file=/usr/local/mysql/data/mysqld.pid

[Install]
WantedBy=multi-user.target

启动 MySQL 服务,加载新的服务文件并启动 MySQL 服务:

# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 启动 MySQL 服务:
sudo systemctl start mysqld
# 将 MySQL 设置为开机自启:
sudo systemctl enable mysqld
# 查看MySQL状态
sudo systemctl status mysqld

登录MySQl(密码是刚才初始化的生成的密码)并修改密码。

/usr/local/mysql/bin/mysql -u root -p
ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';

5. 添加系统变量

目前只能通过 ./bin/mysql -uroot -p 登录,MySQL客户端不在全局环境变量中。想要直接通过MySQL命令访问,必须将MySQL的路径加入到环境变量中。

  1. 编辑环境变量文件:

    sudo nano /etc/profile
    
  2. 在文件末尾添加:

    export PATH=$PATH:/usr/local/mysql/bin
    
  3. 保存并应用更改:

    source /etc/profile
    
  4. 验证是否生效:

    mysql --version
    

6. 修改MySQL密码

参考链接

  1. 修改登录权限
vim /etc/my.cnf
  1. 在[mysqld]部分添加。目的是免密登录。
skip-grant-tables
  1. 重启mysql服务
systemctl restart mysqld
  1. 登录mysql.这里可以直接输入空密码,回车。
mysql -uroot -p
  1. 修改密码
show databases;
use mysql;
show tables;
desc user;  # 可以看到user表里面有一个authentication_string字段
update user set authentication_string=password("123456") where user ='root';

7. openssl编译安装

参考链接

  1. 编译
wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz
 ./config --prefix=/usr/local/openssl
 ./config -t
sudo make
sudo make install
  1. 链接OpenSSL所依赖的库文件
cd /usr/local/openssl/bin
ldd openssl
linux-vdso.so.1 (0x0000ffff905a9000)
libssl.so.1.1 => not found
libcrypto.so.1.1 => not found
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff902f0000)
/lib/ld-linux-aarch64.so.1 (0x0000ffff90570000)

注意not found的两行,意思是libssl.so.1.1和libcrypto.so.1.1找不到所依赖的库文件,直接运行会抛openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory异常,解决方法为手动去连接库文件.

ln -s /usr/local/openssl/lib/libssl.so.1.1 /usr/lib64/libssl.so.1.1
ln -s /usr/local/openssl/lib/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1             
# 临时使用,也可以执行        
export LD_LIBRARY_PATH=/usr/local/openssl/lib:$LD_LIBRARY_PATH

再次,ldd openssl一下

linux-vdso.so.1 (0x0000ffff9a2a9000)
libssl.so.1.1 => /usr/local/openssl/lib/libssl.so.1.1 (0x0000ffff9a0f0000)
libcrypto.so.1.1 => /usr/local/openssl/lib/libcrypto.so.1.1 (0x0000ffff99e30000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff99c80000)
/lib/ld-linux-aarch64.so.1 (0x0000ffff9a270000)
  1. 修改配置文件

在/etc/profile最后一行添加

sudo vim /etc/profile
export OPENSSL=/usr/local/openssl/bin
export PATH=$OPENSSL:$PATH:$HOME/bin
source /etc/profile

验证是否生效

openssl version -a

二、运行代码

  • MySQL启动bug

    × mysqld.service - MySQL Server
         Loaded: loaded (/etc/systemd/system/mysqld.service; enabled; vendor preset: enabled)
         Active: failed (Result: exit-code) since Mon 2024-12-02 10:43:41 UTC; 7h left
        Process: 759 ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --pid-file=/usr/local/mysql/data/mysqld.pid (code=exited, status=1/FAILURE)
       Main PID: 759 (code=exited, status=1/FAILURE)
            CPU: 732ms
    
    Dec 02 10:43:39 elephant systemd[1]: Started MySQL Server.
    Dec 02 10:43:41 elephant systemd[1]: mysqld.service: Main process exited, code=exited, status=1/FAILURE
    Dec 02 10:43:41 elephant systemd[1]: mysqld.service: Failed with result 'exit-code'.
    

    解决:重新加载、启动服务

    systemctl daemon-reload
    systemctl restart mysqld.service
    
  • 创建数据库

    通过终端进入mysql,创建TinyWebServer的数据库和表

    # 进入数据库
    mysql -uroot -p
    #接下来输入密码
    
    // 建立tinywebserver库
    create database tinywebserver;
    // 创建user表
    USE tinywebserver;
    CREATE TABLE user(
        username char(50) NULL,
        passwd char(50) NULL
    )ENGINE=InnoDB;
    
    // 添加数据
    INSERT INTO user(username, passwd) VALUES('elephant', '123456');
    
    // 退出数据库
    exit;
    
  • 开放端口(其实不需要)

    sudo apt install ufw
    sudo ufw allow 9006
    
  • 编译代码

    cd ./TinyWebServer
    chmod +x ./build.sh
    ./build.sh
    # 这里可能回报找不到mysql头文件类似的错误,安装一下依赖即可
    sudo apt-get install mysql-server
    # 再次编译
    ./build.sh
    
  • 日志频繁报错mysql error

    参考这个issue

    在sql_connection_pool.cpp添加下面的调试代码.重新编译,再次运行,会输出数据库的连接错误.

    // con = mysql_real_connect(con, url.c_str(), User.c_str(), PassWord.c_str(), DBName.c_str(), Port, NULL, 0);
    if (!mysql_real_connect(con, url.c_str(), User.c_str(), PassWord.c_str(), DBName.c_str(), Port, NULL, 0))
    {
      cout << mysql_errno(con) << "   " << mysql_error(con) << endl;
      exit(1);
    }
    

    ./server运行:

    2002   Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
    

    这个错误 2002: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)表示 MySQL 客户端尝试通过指定的 Unix 套接字文件 /var/run/mysqld/mysqld.sock 连接 MySQL 服务时失败.

    1. MySQL 服务未运行

      通过systemctl status mysqld很容易验证正在运行。不是这个原因。

    2. 套接字文件不存在

      ls -l /var/run/mysqld/mysqld.sock
      

      没有输出。因此通过这个位置找sokcet文件是连接不上mysql的。

      定位一下mysqld.sock的位置。locate,find都不行,直接在配置文件中找。

      grep -i socket /etc/my.cnf /etc/mysql/my.cnf
      /etc/my.cnf:socket = /tmp/mysql.sock
      /etc/mysql/my.cnf:# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
      

      客户端尝试连接默认的 /var/run/mysqld/mysqld.sock,但服务器使用的是 /tmp/mysql.sock,从而产生无法找到套接字文件的错误。

      **解决方案:**确保服务器和客户端的 socket 设置一致。

      sudo mkdir -p /var/run/mysqld
      sudo ln -s /tmp/mysql.sock /var/run/mysqld/mysqld.sock
      sudo chown mysql:mysql /var/run/mysqld/mysqld.sock
      

      创建软连接将 /tmp/mysql.sock 链接到 /var/run/mysqld/mysqld.sock

      再次运行./server。成功。

三、参考链接

TinyWebServer项目

Mac在VMware Fusion安装Ubuntu22.04

MySQL编译

openssl编译安装

MySQL修改密码

MySQL ERROR

WebServer 跑通/运行/测试(详解版)

c++ 经典服务器开源项目 Tinywebserver的使用与配置(百度智能云服务器安装ubuntu18.04可用公网ip访问)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值