Databases 25 min read

Deploy MySQL 8.4 from Source with a Single Script Across Major Linux Distributions

This guide provides a comprehensive, step‑by‑step shell script that automates the installation, configuration, and service setup of MySQL 8.4 from source on a wide range of Linux distributions, including Rocky, AlmaLinux, CentOS, openEuler, Anolis, OpenCloudOS, Kylin, UOS, openSUSE, Ubuntu, and Debian.

Raymond Ops
Raymond Ops
Raymond Ops
Deploy MySQL 8.4 from Source with a Single Script Across Major Linux Distributions

2.4.2.5 Prepare environment variables

echo 'PATH=/apps/mysql/bin:$PATH' > /etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh

chown -R mysql:mysql /apps/mysql/

2.4.2.6 Generate database files

# /data/mysql will be created automatically, but /data must exist
# --initialize generates an initial password, --initialize-insecure generates an empty password
# Generate initial password
mysqld --initialize --user=mysql --datadir=/data/mysql
# Example log output (truncated)
2025-04-30T14:21:27.126347Z 0 [System] [MY-015017] [Server] MySQL Server Initialization - start.
2025-04-30T14:21:27.130746Z 0 [System] [MY-013169] [Server] /apps/mysql/bin/mysqld (mysqld 8.4.5) initializing of server progress as process 45248
2025-04-30T14:21:27.133400Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4.
2025-04-30T14:21:27.133406Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8mb3_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.
2025-04-30T14:21:28.313966Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: q&VUtowtA6!.
# Generate empty‑password root user
mysqld --initialize-insecure --user=mysql --basedir=/apps/mysql --datadir=/data/mysql
2025-04-30T16:03:40.486647Z 0 [System] [MY-015017] [Server] MySQL Server Initialization - start.
2025-04-30T16:03:40.494615Z 0 [System] [MY-013169] [Server] /apps/mysql/bin/mysqld (mysqld 8.4.5) initializing of server progress as process 46287
2025-04-30T16:03:40.501884Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4.
2025-04-30T16:03:40.501891Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8mb3_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.
2025-04-30T16:03:41.857055Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password! Please consider switching off the --initialize-insecure option.

2.4.2.7 Prepare configuration file

cat > /etc/my.cnf <<EOF
[mysqld]
user=mysql
basedir=/apps/mysql/
datadir=/data/mysql
port=3306
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid

[client]
port=3306
socket=/data/mysql/mysql.sock
EOF

2.4.2.8 Prepare startup script and start service

# Copy the appropriate systemd service file depending on the OS
# Rocky, AlmaLinux, CentOS, openEuler, Anolis, OpenCloudOS, Kylin, UOS, openSUSE
cp /apps/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/
# Ubuntu Server 24.04 LTS
cp /apps/mysql/usr/lib/systemd/system/mysqld.service /lib/systemd/system/
# For Ubuntu 18.04/20.04/22.04 LTS and Debian 11/12 without a provided service file
cat > /lib/systemd/system/mysqld.service <<EOF
[Unit]
Description=MySQL Server
After=network.target

[Service]
User=mysql
Group=mysql
ExecStart=/apps/mysql/bin/mysqld --defaults-file=/etc/my.cnf
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable --now mysqld

2.4.2.9 Modify password

# If an empty password was generated, this step can be skipped
mysqladmin -u root -p'q&VUtowtA6!.' password 123456

2.4.2.10 Login test

mysql
mysql> status;
+-----------------------+
| Variable_name         |
+-----------------------+
| ... (output truncated) |
+-----------------------+
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

2.4.2.11 One‑click MySQL 8.4 source installation script

#!/bin/bash
# ------------------------------------------------------------
# Author: Raymond
# Description: Install MySQL 8.4 from source on many Linux OSes
# ------------------------------------------------------------
COLOR="echo -e \033[01;31m"
END='\033[0m'

# Detect OS name and version
os() {
    . /etc/os-release
    MAIN_NAME=$(sed -rn '/^NAME=/s@.*="([[:alpha:]]+).*"$@\1@p' /etc/os-release)
    if [[ $MAIN_NAME == "Kylin" ]]; then
        MAIN_VERSION_ID=$(sed -rn '/^VERSION_ID=/s@.*="([[:alpha:]]+)(.*)"$@\2@p' /etc/os-release)
    else
        MAIN_VERSION_ID=$(sed -rn '/^VERSION_ID=/s@.*="?([0-9]+)\.?*"?$@\1@p' /etc/os-release)
    fi
    if [[ $MAIN_NAME == "Ubuntu" || $MAIN_NAME == "Debian" ]]; then
        FULL_NAME="$PRETTY_NAME"
    elif [[ $MAIN_NAME == "UOS" ]]; then
        FULL_NAME="$NAME"
    else
        FULL_NAME="$NAME$VERSION_ID"
    fi
}

os
SRC_DIR=/usr/local/src
INSTALL_DIR=/apps/mysql
DATA_DIR=/data/mysql
MYSQL_URL='https://cdn.mysql.com//Downloads/MySQL-8.4/'
MYSQL_FILE='mysql-8.4.5.tar.gz'
CMAKE_URL='https://cmake.org/files/v3.31/'
CMAKE_FILE='cmake-3.31.7-linux-x86_64.tar.gz'
# ... (other URLs and file names omitted for brevity) ...

check_mysql_file() {
    if [[ $MAIN_NAME == "Rocky" || $MAIN_NAME == "AlmaLinux" || $MAIN_NAME == "CentOS" || $MAIN_NAME == "Anolis" || $MAIN_NAME == "OpenCloudOS" || $MAIN_NAME == "Kylin" ]]; then
        rpm -q wget &>/dev/null || { $COLOR "Installing wget..."; $END; yum -y install wget &>/dev/null; }
    fi
    if [[ ! -e $MYSQL_FILE ]]; then
        $COLOR "Downloading MySQL source package..."; $END
        wget ${MYSQL_URL}${MYSQL_FILE} || { $COLOR "MySQL source download failed!"; $END; exit 1; }
    else
        $COLOR "MySQL source package already present."; $END
    fi
}

# Similar functions for CMake, GCC, etc. are defined here (omitted for brevity)

install_mysql() {
    if [[ -d $INSTALL_DIR ]]; then
        $COLOR "MySQL already installed, aborting."; $END; exit 1;
    fi
    $COLOR "Starting MySQL installation..."; $END
    # Create mysql user/group
    id mysql &>/dev/null || { groupadd -r mysql; useradd -s /sbin/nologin -d $DATA_DIR -r -g mysql mysql; $COLOR "Created mysql user."; $END; }
    mkdir -p $DATA_DIR && chown -R mysql:mysql $DATA_DIR
    # Install dependencies based on OS (logic omitted for brevity)
    # Extract source and compile
    tar xf $MYSQL_FILE
    MYSQL_DIR=$(echo $MYSQL_FILE | sed -nr 's/^(.*[0-9]).*/\1/p')
    cd $MYSQL_DIR
    cmake \
        -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR \
        -DMYSQL_UNIX_ADDR=$DATA_DIR/mysql.sock \
        -DSYSCONFDIR=/etc \
        -DSYSTEMD_PID_DIR=$INSTALL_DIR \
        -DDEFAULT_CHARSET=utf8mb4 \
        -DDEFAULT_COLLATION=utf8mb4_general_ci \
        -DWITH_INNOBASE_STORAGE_ENGINE=1 \
        -DWITH_ARCHIVE_STORAGE_ENGINE=1 \
        -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
        -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
        -DMYSQL_DATADIR=$DATA_DIR \
        -DFORCE_INSOURCE_BUILD=1 \
        -DWITH_SYSTEMD=1
    make -j $(nproc) && make install
    if [[ $? -eq 0 ]]; then
        $COLOR "MySQL compiled and installed successfully!"; $END
    else
        $COLOR "MySQL compilation failed, exiting!"; $END; exit 1;
    fi
    echo "PATH=$INSTALL_DIR/bin:\$PATH" > /etc/profile.d/mysql.sh
    . /etc/profile.d/mysql.sh
    chown -R mysql:mysql $INSTALL_DIR
    mysqld --initialize-insecure --user=mysql --basedir=$INSTALL_DIR --datadir=$DATA_DIR
    cat > /etc/my.cnf <<EOF
[mysqld]
user=mysql
basedir=$INSTALL_DIR
datadir=$DATA_DIR
port=3306
socket=$DATA_DIR/mysql.sock
log-error=$DATA_DIR/mysql.log
pid-file=$DATA_DIR/mysql.pid

[client]
port=3306
socket=$DATA_DIR/mysql.sock
EOF
    # Copy appropriate systemd service file
    if [[ $MAIN_NAME == "Rocky" || $MAIN_NAME == "AlmaLinux" || $MAIN_NAME == "CentOS" || $MAIN_NAME == "openEuler" || $MAIN_NAME == "Anolis" || $MAIN_NAME == "OpenCloudOS" || $MAIN_NAME == "Kylin" || $MAIN_NAME == "UOS" || $MAIN_NAME == "openSUSE" ]]; then
        cp $INSTALL_DIR/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/
    elif [[ $MAIN_NAME == "Ubuntu" ]]; then
        cp $INSTALL_DIR/usr/lib/systemd/system/mysqld.service /lib/systemd/system/
    elif [[ $MAIN_NAME == "Debian" ]]; then
        cat > /lib/systemd/system/mysqld.service <<EOF
[Unit]
Description=MySQL Server
After=network.target

[Service]
User=mysql
Group=mysql
ExecStart=$INSTALL_DIR/bin/mysqld --defaults-file=/etc/my.cnf
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
    fi
    systemctl daemon-reload && systemctl enable --now mysqld
    if [[ $? -ne 0 ]]; then
        $COLOR "Failed to start MySQL service, exiting!"; $END; exit 1;
    fi
    $COLOR "$FULL_NAME OS, MySQL installation completed!"; $END
}

main() {
    check_mysql_file
    # Additional checks for CMake, GCC, etc. would be called here
    install_mysql
}

# Dispatch based on detected OS and version
if [[ $MAIN_NAME == "Rocky" && $MAIN_VERSION_ID =~ ^(8|9|10)$ ]]; then
    main
elif [[ $MAIN_NAME == "AlmaLinux" && $MAIN_VERSION_ID =~ ^(8|9|10)$ ]]; then
    main
elif [[ $MAIN_NAME == "CentOS" && $MAIN_VERSION_ID =~ ^(7|8|9|10)$ ]]; then
    main
elif [[ $MAIN_NAME == "openEuler" && $MAIN_VERSION_ID =~ ^(22|24)$ ]]; then
    main
elif [[ $MAIN_NAME == "Anolis" && $MAIN_VERSION_ID =~ ^(8|23)$ ]]; then
    main
elif [[ $MAIN_NAME == "OpenCloudOS" && $MAIN_VERSION_ID =~ ^(8|9)$ ]]; then
    main
elif [[ $MAIN_NAME == "Kylin" && $MAIN_VERSION_ID == 10 ]]; then
    main
elif [[ $MAIN_NAME == "UOS" && $MAIN_VERSION_ID == 20 ]]; then
    main
elif [[ $MAIN_NAME == "openSUSE" && $MAIN_VERSION_ID == 15 ]]; then
    main
elif [[ $MAIN_NAME == "Ubuntu" && $MAIN_VERSION_ID =~ ^(18|20|22|24)$ ]]; then
    main
elif [[ $MAIN_NAME == "Debian" && $MAIN_VERSION_ID =~ ^(11|12|13)$ ]]; then
    main
else
    $COLOR "This script does not support $FULL_NAME OS!"; $END
fi
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

automationLinuxmysqlshell scriptDatabase Installation
Raymond Ops
Written by

Raymond Ops

Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.