Systemd là một phần của Red Hat Enterprise Linux không chỉ được dùng để start, stop service mà còn được dùng để quản lí nhiều items khác. Trong Systemd, Unit được dùng để đại diện cho một đơn vị mà Systemd quản lí
1. Tổng quan về Systemd - Vị trí lưu unit file
Có 3 nơi mà unit file được lưu:
-
/usr/lib/systemd/system
: lưu trữ những default unit file của các service được cài đặt từ RPM package -
/etc/systemd/system
: lưu những custom unit file -
/run/systemd/system
: lưu những unit file được generated automatically
Nếu 1 unit file service được lưu ở cả 3 vị trí, thì thứ tự ưu tiên sẽ là
/run/systemd/system > /etc/systemd/system > /usr/lib/systemd/system
2. Triển khai auto reload systemd service
Đây là sơ đồ dùng để auto reload một server được run bằng service
- node-watcher.path: trong systemd, unit với
.path
được sử dụng để watch file, directory change..path
file này phải đi cùng với file.service
có cùng tên. Khi có sự thay đổi ở file hoặc directory đang monitor, file.service
sẽ được start lên. Trong ví dụ này, file node-watcher.path sẽ monitor sự thay đổi của fileenv.txt
- node-watcher.service:
ExecStart
trong file này sẽ chứa câu lệnh để restart Service đang run Node-server
❓️❓️❓️Vậy tại sao không tạo file watcher .path
cho chính Service đang sun Node-server mà lại phải tạo thêm một file node-watcher.service
nhỉ?
👉️👉️👉️👉️👉️ Đó là vì yêu cầu của ExecStart
ở file .service
được trigger phải thực hiện các tác vụ ở một khoản thời gian nhất định (tức là không được treo process - như cách chúng ta start Node-server và giữ cho process run là không được). Nên mình dùng một dump service chỉ để gọi lệnh restart systemctl restart run-node
.
2.1 Tạo run-node.service để run Nodejs server
Bài viết này không tập trung vào các yêu cầu khi run một server như là 1 file service nên mình chỉ dựng tạm server và make sure là nó work (bỏ qua các yêu cầu về file location, working directory location của Rocky Linux).
Mình sẽ tạo một server bằng NodeJs ở /usr/bin/node-server
, đọc file env.txt
một lần duy nhất ngay khi server được start và 1 API.Get-Env trả về value đọc được từ file /usr/bin/node-server/env.txt
- việc này đảm bảo rằng giá trị trả về của API.Get-env chỉ thay đổi khi server restart.
- Tạo folder
/usr/bin/node-server
- Init Nodejs
- Environment required: Install NodeJs
cd /usr/bin/node-server
npm init -y
npm install
- Tạo file
index.js
: đây là file chứa main code của server
const fs = require('fs');
const express = require('express');
const app = express(); const ENV_PATH = '/usr/bin/node-server/env.txt';
let ENV = {}; // Load env
function loadEnv() { ENV = {}; const lines = fs.readFileSync(ENV_PATH, 'utf-8').split('\n'); for (const line of lines) { if (line.includes('=') && !line.startsWith('#')) { const [key, value] = line.split('='); ENV[key.trim()] = value.trim(); } }
} loadEnv(); app.get('/get-env', (req, res) => { res.json(ENV);
}); const port = ENV.PORT || 3000;
app.listen(port, () => { console.log(`Server is running on port ${port}`);
});
- Cài đặt dependency của Node-server (mình keep simple nhất có thể nhé)
npm i express
- Tạo file env.txt với value:
current_value=123
Sau khi hoàn thành các bước, folder node-server sẽ có cấu trúc như sau:
- Tạo run-node.service
Vì đây là custom service nên mình để nó ở /etc/systemd/system
nhé
touch /etc/systemd/system/run-node.service
nano /etc/systemd/system/run-node.service
File run-node.service
[Unit]
Description=Node.js App that loads /usr/bin/node-server/env.txt
After=network.target [Service]
ExecStart=/usr/bin/node /usr/bin/node-server/index.js
WorkingDirectory=/usr/bin/node-server
Restart=always
RestartSec=3
StandardOutput=journal
StandardError=journal
SyslogIdentifier=node-server [Install]
WantedBy=multi-user.target
WorkingDirectory: Vì Node-server bằng js của mình đang keep simple nhất nên mình để Node-server chạy dựa vào dependency ở /usr/bin/node-server/node-module
luôn nên cần phải khai báo để system biết nhen
Start run-node service
systemctl start run-node
- Kiểm tra Node-server hoạt động thành công: gửi request APi.Get-env
curl -X GET http://localhost:3000/get-env
Result:
Node-server đã run thành công ở port 3000 và đã lấy được current_value là 123
- Thay đổi value của file env.txt và gọi lại API.Get-env để chắc rằng Node-server của chúng ta chỉ đọc file
env.txt
một lần duy nhất khi server được start (kết quả của API.Get-env là không đổi dù của file .env.txt đã được update)
2.2 Tạo service watcher, restart server khi file env.txt thay đổi
- Tạo
/etc/systemd/system/node-watcher.service
touch /etc/systemd/system/node-watcher.service
nano /etc/systemd/system/node-watcher.service
Nội dung của file node-watcher.service
:
[Unit]
Description=Restart run-node service
After=network.target [Service]
ExecStart=systemctl restart run-node [Install]
WantedBy=multi-user.target
- Tạo
/etc/systemd/system/node-watcher.path
* Tên file service ở (1) và (2) phải giống nhau
Nội dung của file node-watcher.path
:
- PathChanged: chứa đường dẫn của file, directory mà chúng ta đang monitor
[Unit]
Description=Watch /usr/bin/node-server/env.txt and run-node.service [Path]
PathChanged=/usr/bin/node-server/env.txt [Install]
WantedBy=default.target
- Start
node-watcher.path
systemctl start node-watcher.path
Khi kiểm tra node-watcher.path
service status ta sẽ được thông tin như sau:
💪💪💪 Tada! Vậy là đã xong, bây giờ chỉ cần thay đổi nội dung của file /usr/bin/node-server/env.txt
là chúng ta sẽ thấy API.Get-env sẽ được cập nhật giá trị