From f8afd3fdc319936948b36e9ee4517abfd2ea0c9c Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Wed, 30 Oct 2024 15:44:40 +0800 Subject: [PATCH 1/5] WIP --- server/embedded-mariadb.js | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/server/embedded-mariadb.js b/server/embedded-mariadb.js index 8aa7134bf2..99535c91d3 100644 --- a/server/embedded-mariadb.js +++ b/server/embedded-mariadb.js @@ -49,6 +49,25 @@ class EmbeddedMariaDB { * @returns {Promise|void} A promise that resolves when the MariaDB is started or void if it is already started */ start() { + this.startChildProcess(); + + return new Promise((resolve) => { + let interval = setInterval(() => { + if (this.started) { + clearInterval(interval); + resolve(); + } else { + log.info("mariadb", "Waiting for Embedded MariaDB to start..."); + } + }, 1000); + }); + } + + /** + * Start the child process + * @returns {void} + */ + startChildProcess() { if (this.childProcess) { log.info("mariadb", "Already started"); return; @@ -63,6 +82,7 @@ class EmbeddedMariaDB { "--datadir=" + this.mariadbDataDir, `--socket=${this.socketPath}`, `--pid-file=${this.runDir}/mysqld.pid`, + "--log-error=" + "/app/data/mariadb-error.log", ]); this.childProcess.on("close", (code) => { @@ -72,8 +92,8 @@ class EmbeddedMariaDB { log.info("mariadb", "Stopped Embedded MariaDB: " + code); if (code !== 0) { - log.info("mariadb", "Try to restart Embedded MariaDB as it is not stopped by user"); - this.start(); + log.error("mariadb", "Try to restart Embedded MariaDB as it is not stopped by user"); + this.startChildProcess(); } }); @@ -86,7 +106,7 @@ class EmbeddedMariaDB { }); let handler = (data) => { - log.debug("mariadb", data.toString("utf-8")); + log.info("mariadb", data.toString("utf-8")); if (data.toString("utf-8").includes("ready for connections")) { this.initDBAfterStarted(); } @@ -94,17 +114,6 @@ class EmbeddedMariaDB { this.childProcess.stdout.on("data", handler); this.childProcess.stderr.on("data", handler); - - return new Promise((resolve) => { - let interval = setInterval(() => { - if (this.started) { - clearInterval(interval); - resolve(); - } else { - log.info("mariadb", "Waiting for Embedded MariaDB to start..."); - } - }, 1000); - }); } /** From 9eb2ab7587afddd97708775f5207daec778a112a Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Sat, 2 Nov 2024 16:52:42 +0800 Subject: [PATCH 2/5] WIP --- server/embedded-mariadb.js | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/server/embedded-mariadb.js b/server/embedded-mariadb.js index 99535c91d3..6899ab02a8 100644 --- a/server/embedded-mariadb.js +++ b/server/embedded-mariadb.js @@ -75,6 +75,38 @@ class EmbeddedMariaDB { this.initDB(); + // Create the mariadb directory if not exists and chown it to the node user + if (!fs.existsSync(this.mariadbDataDir)) { + fs.mkdirSync(this.mariadbDataDir, { + recursive: true, + }); + } + + // Check the owner of the mariadb directory, and change it if necessary + let stat = fs.statSync(this.mariadbDataDir); + if (stat.uid !== 1000 || stat.gid !== 1000) { + fs.chownSync(this.mariadbDataDir, 1000, 1000); + } + + // Check the permission of the mariadb directory, and change it if it is not 755 + if (stat.mode !== 0o755) { + fs.chmodSync(this.mariadbDataDir, 0o755); + } + + // Also create the run directory if not exists and chown it to the node user + if (!fs.existsSync(this.runDir)) { + fs.mkdirSync(this.runDir, { + recursive: true, + }); + } + stat = fs.statSync(this.runDir); + if (stat.uid !== 1000 || stat.gid !== 1000) { + fs.chownSync(this.runDir, 1000, 1000); + } + if (stat.mode !== 0o755) { + fs.chmodSync(this.runDir, 0o755); + } + this.running = true; log.info("mariadb", "Starting Embedded MariaDB"); this.childProcess = childProcess.spawn(this.exec, [ @@ -82,7 +114,8 @@ class EmbeddedMariaDB { "--datadir=" + this.mariadbDataDir, `--socket=${this.socketPath}`, `--pid-file=${this.runDir}/mysqld.pid`, - "--log-error=" + "/app/data/mariadb-error.log", + // Don't add the following option, the mariadb will not report message to the console, which affects initDBAfterStarted() + // "--log-error=" + `${this.mariadbDataDir}/mariadb-error.log`, ]); this.childProcess.on("close", (code) => { From a17bd03c0433425bbec94fdf3a7522634ac6f46a Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Sat, 2 Nov 2024 18:04:08 +0800 Subject: [PATCH 3/5] WIP --- server/database.js | 2 +- server/embedded-mariadb.js | 28 +++++++++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/server/database.js b/server/database.js index 3927d6db88..3b7646de8c 100644 --- a/server/database.js +++ b/server/database.js @@ -296,7 +296,7 @@ class Database { client: "mysql2", connection: { socketPath: embeddedMariaDB.socketPath, - user: "node", + user: embeddedMariaDB.username, database: "kuma", timezone: "Z", typeCast: function (field, next) { diff --git a/server/embedded-mariadb.js b/server/embedded-mariadb.js index 6899ab02a8..252f81e2cf 100644 --- a/server/embedded-mariadb.js +++ b/server/embedded-mariadb.js @@ -14,9 +14,15 @@ class EmbeddedMariaDB { mariadbDataDir = "/app/data/mariadb"; - runDir = "/app/data/run/mariadb"; + runDir = "/app/data/run"; - socketPath = this.runDir + "/mysqld.sock"; + socketPath = this.runDir + "/mariadb.sock"; + + /** + * The username to connect to the MariaDB + * @type {string} + */ + username = null; /** * @type {ChildProcessWithoutNullStreams} @@ -49,6 +55,12 @@ class EmbeddedMariaDB { * @returns {Promise|void} A promise that resolves when the MariaDB is started or void if it is already started */ start() { + // Check if the current user is "node" or "root" + this.username = require("os").userInfo().username; + if (this.username !== "node" && this.username !== "root") { + throw new Error("Embedded Mariadb supports only 'node' or 'root' user, but the current user is: " + this.username); + } + this.startChildProcess(); return new Promise((resolve) => { @@ -73,8 +85,6 @@ class EmbeddedMariaDB { return; } - this.initDB(); - // Create the mariadb directory if not exists and chown it to the node user if (!fs.existsSync(this.mariadbDataDir)) { fs.mkdirSync(this.mariadbDataDir, { @@ -107,6 +117,8 @@ class EmbeddedMariaDB { fs.chmodSync(this.runDir, 0o755); } + this.initDB(); + this.running = true; log.info("mariadb", "Starting Embedded MariaDB"); this.childProcess = childProcess.spawn(this.exec, [ @@ -171,9 +183,11 @@ class EmbeddedMariaDB { recursive: true, }); - let result = childProcess.spawnSync("mysql_install_db", [ + let result = childProcess.spawnSync("mariadb-install-db", [ "--user=node", - "--ldata=" + this.mariadbDataDir, + "--auth-root-socket-user=node", + "--datadir=" + this.mariadbDataDir, + "--auth-root-authentication-method=socket", ]); if (result.status !== 0) { @@ -201,7 +215,7 @@ class EmbeddedMariaDB { async initDBAfterStarted() { const connection = mysql.createConnection({ socketPath: this.socketPath, - user: "node", + user: this.username, }); let result = await connection.execute("CREATE DATABASE IF NOT EXISTS `kuma`"); From dfba420d8eac12a52be76bd6c3ac8f5881413236 Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Sat, 2 Nov 2024 18:09:41 +0800 Subject: [PATCH 4/5] Fix lint --- server/embedded-mariadb.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/embedded-mariadb.js b/server/embedded-mariadb.js index 252f81e2cf..6dc93c348e 100644 --- a/server/embedded-mariadb.js +++ b/server/embedded-mariadb.js @@ -52,6 +52,7 @@ class EmbeddedMariaDB { /** * Start the embedded MariaDB + * @throws {Error} If the current user is not "node" or "root" * @returns {Promise|void} A promise that resolves when the MariaDB is started or void if it is already started */ start() { From 37d8ae8fdcdcf8db2c6471dc87daac2411b6b261 Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Tue, 5 Nov 2024 01:33:26 +0800 Subject: [PATCH 5/5] WIP --- server/embedded-mariadb.js | 54 ++++++++++++++------------------------ 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/server/embedded-mariadb.js b/server/embedded-mariadb.js index 6dc93c348e..7c9630dd79 100644 --- a/server/embedded-mariadb.js +++ b/server/embedded-mariadb.js @@ -62,6 +62,8 @@ class EmbeddedMariaDB { throw new Error("Embedded Mariadb supports only 'node' or 'root' user, but the current user is: " + this.username); } + this.initDB(); + this.startChildProcess(); return new Promise((resolve) => { @@ -86,40 +88,6 @@ class EmbeddedMariaDB { return; } - // Create the mariadb directory if not exists and chown it to the node user - if (!fs.existsSync(this.mariadbDataDir)) { - fs.mkdirSync(this.mariadbDataDir, { - recursive: true, - }); - } - - // Check the owner of the mariadb directory, and change it if necessary - let stat = fs.statSync(this.mariadbDataDir); - if (stat.uid !== 1000 || stat.gid !== 1000) { - fs.chownSync(this.mariadbDataDir, 1000, 1000); - } - - // Check the permission of the mariadb directory, and change it if it is not 755 - if (stat.mode !== 0o755) { - fs.chmodSync(this.mariadbDataDir, 0o755); - } - - // Also create the run directory if not exists and chown it to the node user - if (!fs.existsSync(this.runDir)) { - fs.mkdirSync(this.runDir, { - recursive: true, - }); - } - stat = fs.statSync(this.runDir); - if (stat.uid !== 1000 || stat.gid !== 1000) { - fs.chownSync(this.runDir, 1000, 1000); - } - if (stat.mode !== 0o755) { - fs.chmodSync(this.runDir, 0o755); - } - - this.initDB(); - this.running = true; log.info("mariadb", "Starting Embedded MariaDB"); this.childProcess = childProcess.spawn(this.exec, [ @@ -200,6 +168,17 @@ class EmbeddedMariaDB { } } + // Check the owner of the mariadb directory, and change it if necessary + let stat = fs.statSync(this.mariadbDataDir); + if (stat.uid !== 1000 || stat.gid !== 1000) { + fs.chownSync(this.mariadbDataDir, 1000, 1000); + } + + // Check the permission of the mariadb directory, and change it if it is not 755 + if (stat.mode !== 0o755) { + fs.chmodSync(this.mariadbDataDir, 0o755); + } + if (!fs.existsSync(this.runDir)) { log.info("mariadb", `Embedded MariaDB: ${this.runDir} is not found, create one now.`); fs.mkdirSync(this.runDir, { @@ -207,6 +186,13 @@ class EmbeddedMariaDB { }); } + stat = fs.statSync(this.runDir); + if (stat.uid !== 1000 || stat.gid !== 1000) { + fs.chownSync(this.runDir, 1000, 1000); + } + if (stat.mode !== 0o755) { + fs.chmodSync(this.runDir, 0o755); + } } /**