Mashqlar — Node.js ilovani systemd xizmatiga aylantirish
Muammodan boshlaylik
Sizda oddiy Node.js API bor. Vazifa — uni "haqiqiy" xizmatga aylantirish:
- Alohida foydalanuvchi nomidan ishlaydi
- Server yuklanganda o'zi ishga tushadi
- Qulasa — qayta ko'tariladi
- SIGTERM da to'g'ri yopiladi
- Loglari journald da
- Xotirasi cheklangan
Bu — 18–27-darslarning hammasi bir joyda. WSL da ham ishlaydi (systemd yoqilgan bo'lsa — pastdagi eslatmaga qarang).
[!INFO] WSL da systemd:
/etc/wsl.conffaylida[boot]bo'limigasystemd=trueqo'shing, keyin PowerShell dawsl --shutdownva Ubuntu ni qayta oching. Tekshirish:systemctl --version. Yangi WSL o'rnatmalarida odatda allaqachon yoqilgan.
Tayyorgarlik: ilova
Node.js o'rnatilganini tekshiring (node -v). Bo'lmasa:
sudo apt install -y nodejs
Oddiy ilova (hech qanday paketsiz):
sudo mkdir -p /opt/salom
sudo tee /opt/salom/server.js > /dev/null << 'EOF'
const http = require('http');
const PORT = process.env.PORT || 3000;
let sorovlar = 0;
const server = http.createServer((req, res) => {
sorovlar++;
if (req.url === '/crash') {
console.error('Ataylab qulatilmoqda!');
process.exit(1);
}
if (req.url === '/leak') {
global.axlat = global.axlat || [];
for (let i = 0; i < 1e6; i++) global.axlat.push({ i, s: 'x'.repeat(100) });
console.warn('Xotira:', Math.round(process.memoryUsage().rss / 1e6), 'MB');
}
res.end(`Salom! So'rov #${sorovlar}, PID ${process.pid}, foydalanuvchi ${process.env.USER || require('os').userInfo().username}\n`);
});
server.listen(PORT, () => console.log(`Ishga tushdi: ${PORT}-port, PID ${process.pid}`));
process.on('SIGTERM', () => {
console.log('SIGTERM olindi, ulanishlar yopilmoqda...');
server.close(() => {
console.log('Toza yopildi.');
process.exit(0);
});
});
EOF
Qo'lda sinang:
node /opt/salom/server.js
# boshqa terminalda: curl localhost:3000
# Ctrl+C bilan to'xtating
1-mashq: Foydalanuvchi va ruxsatlar
salomnomli tizim foydalanuvchisini yarating (uy papkasiz, kirish huquqisiz)/opt/salomning egasini unga o'zgartiring- Fayllar ruxsati: papka
750, fayl640 salomfoydalanuvchisi nomidan faylni o'qish mumkinligini tekshiring
Yechim
sudo useradd --system --no-create-home --shell /usr/sbin/nologin salom
sudo chown -R salom:salom /opt/salom
sudo chmod 750 /opt/salom
sudo chmod 640 /opt/salom/server.js
sudo -u salom cat /opt/salom/server.js | head -3
id salom
2-mashq: Unit fayl
/etc/systemd/system/salom.service ni yozing:
salomfoydalanuvchisi nomidanPORT=3000muhit o'zgaruvchisi- Xato bilan chiqsa — 3 soniyadan keyin qayta ishga tushsin
- Yuklanishda avtomatik ishga tushsin
Keyin yoqing va holatini tekshiring.
Yechim
which node # masalan: /usr/bin/node
sudo tee /etc/systemd/system/salom.service > /dev/null << 'EOF'
[Unit]
Description=Salom API
After=network.target
[Service]
Type=simple
User=salom
Group=salom
WorkingDirectory=/opt/salom
Environment=PORT=3000
ExecStart=/usr/bin/node /opt/salom/server.js
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now salom
systemctl status salom
curl localhost:3000
curl javobida foydalanuvchi — salom.
3-mashq: Qulash va tiklanish
curl localhost:3000/crash— ilovani qulating- Darhol
systemctl status salom— nima ko'rinyapti? - 3 soniyadan keyin yana
curl localhost:3000— PID o'zgardimi? - Loglardan qulash va qayta ishga tushishni toping
Yechim
curl localhost:3000/crash
systemctl status salom # activating (auto-restart)
sleep 4
curl localhost:3000 # yangi PID
journalctl -u salom -n 20 --no-pager
... Ataylab qulatilmoqda!
... salom.service: Main process exited, code=exited, status=1/FAILURE
... salom.service: Scheduled restart job, restart counter is at 1.
... Ishga tushdi: 3000-port, PID 5122
Restart=on-failure — chiqish kodi 0 bo'lmagani uchun qayta ishga tushirildi.
4-mashq: To'g'ri to'xtatish
sudo systemctl stop salom— loglarda nima bo'lganini ko'ring- Qancha vaqt ketdi? (
timebilan) - To'xtatilgandan keyin qayta ishga tushdimi? Nega?
Yechim
time sudo systemctl stop salom
journalctl -u salom -n 5 --no-pager
... SIGTERM olindi, ulanishlar yopilmoqda...
... Toza yopildi.
... salom.service: Deactivated successfully.
Bir zumda — chunki ilova SIGTERM ni ushlaydi (23-dars). Qayta ishga tushmadi: stop — qo'lda to'xtatish, va ilova exit(0) bilan chiqdi — on-failure faqat xatolarda ishlaydi.
sudo systemctl start salom
5-mashq: Xotira chegarasi
- Unit faylga
MemoryMax=150Mqo'shing - Qayta yuklang
curl localhost:3000/leakni bir necha marta chaqiring- Nima bo'ldi? Loglardan toping
Yechim
[Service] bo'limiga qo'shing:
sudo sed -i '/^RestartSec=3/a MemoryMax=150M' /etc/systemd/system/salom.service
sudo systemctl daemon-reload
sudo systemctl restart salom
systemctl show salom -p MemoryMax
for i in 1 2 3 4 5; do curl -s localhost:3000/leak; done
systemctl status salom
journalctl -u salom -n 15 --no-pager
... Xotira: 112 MB
... salom.service: A process of this unit has been killed by the OOM killer.
... salom.service: Failed with result 'oom-kill'.
... salom.service: Scheduled restart job, restart counter is at 2.
Chegara oshganda faqat shu xizmat o'ldirildi va qayta tug'ildi — server va boshqa xizmatlar zarar ko'rmadi. Docker dagi --memory ham aynan shu mexanizmda (cgroups) ishlaydi.
6-mashq: Xavfsizlik
systemd-analyze security salom— baho qancha?- Unit faylga
NoNewPrivileges,ProtectSystem=strict,ProtectHome,PrivateTmpqo'shing - Ilova ishlayotganini va baho yaxshilanganini tekshiring
Yechim
systemd-analyze security salom | tail -1
# → Overall exposure level for salom.service: 9.2 UNSAFE
sudo sed -i '/^MemoryMax=150M/a NoNewPrivileges=true\nProtectSystem=strict\nProtectHome=true\nPrivateTmp=true' \
/etc/systemd/system/salom.service
sudo systemctl daemon-reload
sudo systemctl restart salom
curl localhost:3000
systemd-analyze security salom | tail -1
# → ... 6.1 MEDIUM
Ilova faqat o'qiydi va tarmoqqa javob beradi — yozish kerak emas, shuning uchun ProtectSystem=strict uni buzmaydi.
7-mashq: Qayta yuklanish sinovi (VPS yoki VM da)
Server qayta yuklangandan keyin xizmat o'zi ishga tushishini tekshiring.
Yechim
systemctl is-enabled salom # enabled
sudo reboot
# ... qayta ulanib:
systemctl is-active salom # active
curl localhost:3000
journalctl -u salom -b # joriy yuklanishdagi loglar
WSL da: PowerShell da wsl --shutdown, keyin Ubuntu ni qayta oching.
Tozalash
sudo systemctl disable --now salom
sudo rm /etc/systemd/system/salom.service
sudo systemctl daemon-reload
sudo rm -rf /opt/salom
sudo userdel salom
Nima uchun shunday?
Nima uchun bu mashqlarda ilovani ataylab qulatdik va xotirani to'ldirdik?
Chunki tiklanish mexanizmlarini ular kerak bo'lmaguncha sinamasangiz — ular ishlashiga ishonch yo'q. Ko'p jamoalar Restart= ni yozib qo'yadi, lekin birinchi haqiqiy qulashda ma'lum bo'ladiki, ExecStart dagi yo'l noto'g'ri, yoki foydalanuvchi faylni o'qiy olmaydi, yoki enable unutilgan. Ataylab buzish — "chaos engineering" ning eng oddiy shakli: muvaffaqiyatsizlikni nazorat ostida keltirib chiqarib, tizim kutilgandek javob berishini tekshirish. Production da emas — aynan shunday mashqda.
Xulosa
Siz mashq qildingiz:
- Tizim foydalanuvchisi,
chown,chmod 750/640,sudo -u - Unit fayl:
User,Environment,ExecStart,Restart=on-failure daemon-reload,enable --now,status,stop- Qulashdan avtomatik tiklanish va loglardan kuzatish
- SIGTERM bilan toza to'xtatish
MemoryMax— xotira chegarasi va OOMProtectSystem,NoNewPrivileges— izolyatsiyasystemd-analyze security— xavfsizlik bahosi
Keyingi bo'lim
6-bo'lim: Paketlar va muhit — apt, PATH, .bashrc, arxivlar.