Час зібрати все вивчене в один справжній продукт. На кінець уроку в тебе буде сторінка
http://91.219.61.30:<порт>/pulse.html, яка сама оновлюється кожні
30 секунд і показує живий стан сервера: час роботи, памʼять, диск, твоє імʼя.
Це твій перший «бекенд + фронтенд» проєкт.
cd, ls, nano~/www/curlnohup для фонуps, killsubprocess, цикл while, cronЗаходь на сервер (як у завданні 01) і створюй файл проєкту в домашній папці:
ssh [email protected] cd ~ nano pulse.py
Встав цей код. Пояснення кожного рядка — у коментарях:
import subprocess # щоб викликати команди shell з Python import datetime # щоб отримати поточний час def run(cmd): # виконує команду в shell і повертає її вивід як рядок return subprocess.check_output(cmd, shell=True, text=True).strip() print("⏱ Час: ", datetime.datetime.now()) print("⏳ Uptime: ", run("uptime -p")) print("💾 Памʼять:", run("free -h | awk '/Mem:/ {print $3 \"/\" $2}'")) print("📀 Диск: ", run("df -h / | awk 'NR==2 {print $3 \"/\" $2}'"))
Збережи (Ctrl+O, Enter, Ctrl+X) і запусти:
python3 pulse.py
Маєш побачити приблизно:
⏱ Час: 2026-05-02 14:31:08.421 ⏳ Uptime: up 12 days, 4 hours, 2 minutes 💾 Памʼять: 1.4G/3.8G 📀 Диск: 18G/40G
subprocess — це міст між Python і командним рядком. run("uptime -p") робить те саме, що ти набрав би в терміналі вручну, тільки результат потрапляє в Python.~/www/Тепер той самий скрипт буде не друкувати в термінал, а записувати HTML у твою публічну папку. Сторінка одразу стане доступна в інтернеті.
Відкрий nano pulse.py і заміни весь вміст на:
import subprocess import datetime USER = "bodko.v" # ← ЗАМІНИ на свій логін! OUT = f"/home/{USER}/www/pulse.html" def run(cmd): return subprocess.check_output(cmd, shell=True, text=True).strip() now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") uptime = run("uptime -p") mem = run("free -h | awk '/Mem:/ {print $3 \"/\" $2}'") disk = run("df -h / | awk 'NR==2 {print $3 \"/\" $2}'") html = f"""<!doctype html> <html lang="uk"><head><meta charset="utf-8"> <meta http-equiv="refresh" content="30"> <title>Pulse — {USER}</title> <style> body {{ font-family:monospace; background:#0a0a12; color:#e8e8f3; padding:40px; max-width:600px; margin:auto; }} h1 {{ color:#fcee0a; }} .row {{ display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid #222; }} .v {{ color:#00d9ff; }} .ok{{ color:#39ff14; }} </style></head><body> <h1>💓 Pulse — {USER}</h1> <div class="row"><span>Оновлено</span><span class="v">{now}</span></div> <div class="row"><span>Uptime</span><span class="v">{uptime}</span></div> <div class="row"><span>Памʼять</span><span class="v">{mem}</span></div> <div class="row"><span>Диск</span><span class="v">{disk}</span></div> <p class="ok">● online</p> </body></html>""" with open(OUT, "w") as f: f.write(html) print(f"✓ Записано {len(html)} байт у {OUT}")
Запусти й перевір у браузері:
python3 pulse.py
# має вивести: ✓ Записано XXXX байт у /home/bodko.v/www/pulse.html
Тепер відкрий: http://91.219.61.30:9000/pulse.html (заміни порт на свій).
<meta http-equiv="refresh" content="30"> — це команда браузеру самому перевантажувати сторінку кожні 30 секунд.403 Forbidden — у файла немає прав на читання. Виконай: chmod 644 ~/www/pulse.html.Зараз скрипт спрацьовує один раз. Хочемо — щоб він сам перезаписував файл кожні 30 секунд. Додамо нескінченний цикл.
На самому початку файла додай:
import time
А весь блок «отримання даних + запис файла» оберни в while True:. Кінець скрипта тепер виглядає так:
while True: now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") uptime = run("uptime -p") mem = run("free -h | awk '/Mem:/ {print $3 \"/\" $2}'") disk = run("df -h / | awk 'NR==2 {print $3 \"/\" $2}'") html = f"""...""" # шаблон HTML такий самий, як у Стадії 2 with open(OUT, "w") as f: f.write(html) print(f"[{now}] оновлено") time.sleep(30) # почекати 30 секунд
Запусти й залиш у терміналі:
python3 pulse.py
Кожні 30 секунд має зʼявлятись новий рядок [2026-05-02 14:32:07] оновлено. Тримай браузер відкритим — побачиш як міняється час.
Зупини скрипт Ctrl+C. У наступній стадії запустимо його у фоні.
while True? Це цикл, який ніколи не завершується сам. Кожна ітерація = одне оновлення сторінки. time.sleep(30) приспає процес і не вантажитиме CPU.Згадай завдання 08 — nohup від'єднує процес від твого SSH-зʼєднання. Скрипт виживе після того, як ти закриєш термінал.
nohup python3 pulse.py > pulse.log 2>&1 &
echo $! # ← запамʼятай цей номер (PID)
Перевір, що процес живий:
ps -p <PID>
# має показати рядок з python3
Спостерігай за логом у реальному часі:
tail -f pulse.log # кожні 30 сек має зʼявлятись "[YYYY-MM-DD HH:MM:SS] оновлено" # Ctrl+C — щоб припинити спостерігати (процес не зупиниться)
Тепер можеш сміливо exit з SSH — сторінка pulse.html й далі оновлюватиметься 24/7.
Уяви: ти зайшов завтра, $! вже забув, але хочеш зупинити свій pulse. Як знайти?
# усі твої python-процеси ps -u $USER | grep python # шукаємо саме pulse.py за назвою pgrep -af pulse.py
Виведе щось типу:
847291 python3 pulse.py
# curl бачить заголовок Last-Modified — час останнього запису файла curl -sI http://91.219.61.30:9000/pulse.html | grep -i modified # має показати свіжий час, не старіший за 30 сек
kill <PID>
# або одразу всіх python-процесів від твого імені:
pkill -u $USER -f pulse.py
Перевір, що дійсно зупинено:
pgrep -af pulse.py
# нічого не виводить — процес мертвий ✓
while TrueУ реальних проєктах nohup + while True — це костиль для навчання. Промисловий стандарт — планувальник cron: він сам запускає твій скрипт за розкладом, і тобі не треба тримати процес у памʼяті.
Видали з pulse.py:
import timewhile True:time.sleep(30)Тобто скрипт знов виконує запис один раз і завершується.
crontab -e
Якщо вперше — спитає редактор, обери nano. У файл, що відкриється, додай один рядок в кінець:
* * * * * /usr/bin/python3 /home/bodko.v/pulse.py >> /home/bodko.v/pulse.log 2>&1
Збережи (Ctrl+O, Ctrl+X). cron сам видасть:
crontab: installing new crontab
* * * * * команда │ │ │ │ │ │ │ │ │ └─ день тижня (0-6, 0=неділя) │ │ │ └─── місяць (1-12) │ │ └───── день місяця (1-31) │ └─────── година (0-23) └───────── хвилина (0-59) * * * * * = щохвилини */5 * * * * = кожні 5 хвилин 0 9 * * 1 = щопонеділка о 9:00
crontab -l # показати свій список завдань tail -f pulse.log # бачити, як cron додає рядки
while True впаде один раз — і все, mert. Cron — як вічний двигун.crontab -e # видали свій рядок, збережи # або видалити всі свої cron-завдання разом: crontab -r
5 запитань. Спочатку дай свою відповідь у голові — потім розгорни.
22 і ті самі логін/пароль.
python3 bot.py, потім закрив SSH — і бот помер. Чому?SIGHUP (hang up — «трубку поклали»), і вони завершуються. Виправлення: запускати через nohup … &, tmux або зробити сервіс через systemd.
nohup python3 bot.py > log.txt 2>&1 &?nohup — ігнорувати SIGHUP, не вмирати при виході з SSH.> log.txt — стандартний вивід (print) у файл log.txt.2>&1 — потік помилок (stderr, номер 2) направити туди ж, куди й вивід (stdout, номер 1).& — у фон, термінал одразу вільний.
pgrep -af pulse.py — покаже PID + повну команду.pkill -u $USER -f pulse.py.-u $USER — тільки твої процеси, -f — шукати в повному рядку команди (а не тільки в назві бінарника).
TOKEN = "..." прямо в коді — це погана практика?.env файлі, який не комітиться в git, і читати через os.environ["TOKEN"].