{"id":498492,"date":"2026-10-13T17:15:44","date_gmt":"2026-10-13T14:15:44","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=498492"},"modified":"2026-10-13T17:15:44","modified_gmt":"2026-10-13T14:15:44","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=498492","title":{"rendered":"\u041a\u0430\u043a\u00a0\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 Python\u2011\u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430\u00a0VPS: systemd, \u043b\u043e\u0433\u0438, \u0430\u0432\u0442\u043e\u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0438 \u0430\u043b\u0435\u0440\u0442\u044b \u0432\u00a0Telegram"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0423\u00a0\u043c\u0435\u043d\u044f \u043d\u0430\u00a0VPS \u0436\u0438\u0432\u0451\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u043b\u043a\u0438\u0445 Python\u2011\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432: \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443 \u0447\u0442\u043e\u2011\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u00a0\u0443\u0442\u0440\u0430\u043c \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0442\u0447\u0451\u0442. \u0420\u0430\u043d\u044c\u0448\u0435 \u043e\u043d\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438\u0441\u044c \u0447\u0435\u0440\u0435\u0437 <code>nohup python app.py &amp;<\/code> \u0438\u043b\u0438\u00a0\u0432 <code>screen<\/code>. \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043e\u00a0\u043f\u0435\u0440\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u043b\u0438\u00a0\u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u043e\u0433\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u041f\u043e\u0442\u043e\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0442\u0438\u0445\u043e \u043b\u0435\u0436\u0438\u0442, \u0430\u00a0\u0443\u0437\u043d\u0430\u0451\u0448\u044c \u043e\u0431\u00a0\u044d\u0442\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u043a\u0442\u043e\u2011\u0442\u043e \u0441\u043f\u0440\u043e\u0441\u0438\u0442, \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u00a0\u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u0441\u0445\u0435\u043c\u0430, \u043a\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u044f \u043f\u0440\u0438\u0448\u0451\u043b. \u041e\u043d\u0430 \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u0447\u0435\u0442\u044b\u0440\u0435 \u0444\u0430\u0439\u043b\u0430 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e\u00a0\u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432\u00a0\u043b\u044e\u0431\u043e\u043c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u0435: systemd \u0438 journald. Docker, supervisord \u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u043d\u0435\u00a0\u043d\u0443\u0436\u043d\u044b.<\/p>\n<h3>\u0420\u0430\u0441\u043a\u043b\u0430\u0434\u043a\u0430<\/h3>\n<pre><code>\/opt\/myapp\/            \u043a\u043e\u0434 \u0438 .venv\/opt\/myapp\/data\/       \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u043f\u0430\u043f\u043a\u0430, \u043a\u0443\u0434\u0430 \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0438\u0448\u0435\u0442\/etc\/myapp.env         \u0441\u0435\u043a\u0440\u0435\u0442\u044b, chmod 600, \u0432\u043b\u0430\u0434\u0435\u043b\u0435\u0446 root<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper\"><\/span><\/a><\/div><\/pre>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0442\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0431\u0435\u0437\u00a0shell:<\/p>\n<pre><code class=\"bash\">sudo useradd --system --home-dir \/opt\/myapp --shell \/usr\/sbin\/nologin myappsudo chown -R myapp: \/opt\/myapp\/data<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0424\u0430\u0439\u043b <code>\/etc\/myapp.env<\/code> \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442\u044c root: systemd \u0447\u0438\u0442\u0430\u0435\u0442 <code>EnvironmentFile<\/code> \u0441\u0430\u043c, \u0434\u043e\u00a0\u0442\u043e\u0433\u043e \u043a\u0430\u043a\u00a0\u0441\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0421\u0430\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043d\u0435\u00a0\u0441\u043c\u043e\u0436\u0435\u0442, \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h3>\u0421\u0435\u0440\u0432\u0438\u0441 \u0441\u00a0\u0430\u0432\u0442\u043e\u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c<\/h3>\n<p><code>\/etc\/systemd\/system\/myapp.service<\/code>:<\/p>\n<pre><code class=\"ini\">[Unit]Description=myapp workerAfter=network-online.targetWants=network-online.targetOnFailure=tg-notify@%n.serviceStartLimitIntervalSec=300StartLimitBurst=5[Service]User=myappWorkingDirectory=\/opt\/myappExecStart=\/opt\/myapp\/.venv\/bin\/python app.pyEnvironmentFile=\/etc\/myapp.envEnvironment=PYTHONUNBUFFERED=1Restart=on-failureRestartSec=5NoNewPrivileges=yesPrivateTmp=yesProtectSystem=strictProtectHome=yesReadWritePaths=\/opt\/myapp\/data[Install]WantedBy=multi-user.target<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e\u00a0\u0437\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><code>Restart=on-failure<\/code> \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u043a\u0440\u0438\u043f\u0442, \u0435\u0441\u043b\u0438 \u043e\u043d \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f \u0441\u00a0\u043d\u0435\u043d\u0443\u043b\u0435\u0432\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0438\u043b\u0438\u00a0\u0435\u0433\u043e \u0443\u0431\u0438\u043b\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u043c. \u0415\u0441\u043b\u0438 \u0432\u044b \u0441\u0430\u043c\u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 <code>systemctl stop<\/code>, \u043e\u043d \u043d\u0435\u00a0\u043f\u043e\u0434\u043d\u0438\u043c\u0435\u0442\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p><code>StartLimitIntervalSec<\/code> \u0438 <code>StartLimitBurst<\/code> \u0441\u0442\u043e\u044f\u0442 \u0432 <code>[Unit]<\/code>, \u0430\u00a0\u043d\u0435\u00a0\u0432 <code>[Service]<\/code>. \u0415\u0441\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u0443\u043f\u0430\u043b 5\u00a0\u0440\u0430\u0437 \u0437\u0430 5\u00a0\u043c\u0438\u043d\u0443\u0442, systemd \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0451\u0442 \u0435\u0433\u043e \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442 \u0432\u00a0\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 failed. \u0411\u0435\u0437\u00a0\u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442 \u0441\u00a0\u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u0432\u00a0\u043a\u043e\u043d\u0444\u0438\u0433\u0435 \u0431\u0443\u0434\u0435\u0442 \u043a\u0440\u0443\u0442\u0438\u0442\u044c\u0441\u044f \u0432\u00a0\u0446\u0438\u043a\u043b\u0435 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p><code>PYTHONUNBUFFERED=1<\/code> \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b <code>print<\/code> \u0438 \u043b\u043e\u0433\u0438 \u043f\u043e\u043f\u0430\u0434\u0430\u043b\u0438 \u0432\u00a0\u0436\u0443\u0440\u043d\u0430\u043b \u0441\u0440\u0430\u0437\u0443, \u0430\u00a0\u043d\u0435\u00a0\u043f\u0430\u0447\u043a\u043e\u0439 \u043f\u0440\u0438\u00a0\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0411\u043b\u043e\u043a \u0438\u0437 <code>ProtectSystem=strict<\/code> \u0438 \u0441\u043e\u0441\u0435\u0434\u0435\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 \u0444\u0430\u0439\u043b\u043e\u0432\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 read\u2011only \u0434\u043b\u044f\u00a0\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u043a\u0440\u043e\u043c\u0435 <code>ReadWritePaths<\/code>. \u0414\u043b\u044f\u00a0\u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u043e\u0434\u0438\u0442 \u0432\u00a0\u0447\u0443\u0436\u0438\u0435 API, \u044d\u0442\u043e \u0434\u0435\u0448\u0451\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u0445\u043e\u0432\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430:<\/p>\n<pre><code class=\"bash\">sudo systemctl daemon-reloadsudo systemctl enable --now myappsystemctl status myapp<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u00a0\u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0443\u0431\u0435\u0439\u0442\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441: <code>sudo systemctl kill -s KILL myapp<\/code>. \u0427\u0435\u0440\u0435\u0437 5\u00a0\u0441\u0435\u043a\u0443\u043d\u0434 <code>systemctl status<\/code> \u0441\u043d\u043e\u0432\u0430 \u043f\u043e\u043a\u0430\u0436\u0435\u0442 active, \u0430 <code>systemctl show myapp -p NRestarts<\/code> \u0432\u0435\u0440\u043d\u0451\u0442 1.<\/p>\n<h3>\u041b\u043e\u0433\u0438: \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0448\u0438\u0442\u0435 \u0432\u00a0stdout<\/h3>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043b\u043e\u0433\u2011\u0444\u0430\u0439\u043b\u044b \u0441\u00a0\u0440\u043e\u0442\u0430\u0446\u0438\u0435\u0439 \u043d\u0435\u00a0\u043d\u0443\u0436\u043d\u044b. \u0412\u0441\u0451, \u0447\u0442\u043e\u00a0\u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0438\u0448\u0435\u0442 \u0432\u00a0stdout \u0438 stderr, \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432\u00a0journald \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u00a0\u0442\u0440\u0435\u0439\u0441\u0431\u044d\u043a\u0430\u043c\u0438. \u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"bash\">journalctl -u myapp -f                   # \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438journalctl -u myapp --since \"1 hour ago\"journalctl -u myapp -p err               # \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0448\u0438\u0431\u043a\u0438journalctl --disk-usage<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b <code>-p err<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u043b, journald \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u043d\u0430\u0442\u044c \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u0442\u0440\u043e\u043a\u0438. \u041e\u043d \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u0432\u0438\u0434\u0430 <code>&lt;3&gt;<\/code> \u0432\u00a0\u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 (\u044d\u0442\u043e \u0443\u0440\u043e\u0432\u043d\u0438 syslog), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0442\u0435\u0440\u0430:<\/p>\n<pre><code class=\"python\">import loggingimport sysclass JournalFormatter(logging.Formatter):    \"\"\"\u041f\u0440\u0435\u0444\u0438\u043a\u0441 &lt;N&gt; journald \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0437\u0430\u043f\u0438\u0441\u0438.\"\"\"    PRIORITY = {logging.DEBUG: 7, logging.INFO: 6, logging.WARNING: 4,                logging.ERROR: 3, logging.CRITICAL: 2}    def format(self, record):        prio = self.PRIORITY.get(record.levelno, 6)        return f\"&lt;{prio}&gt;{record.name}: {super().format(record)}\"handler = logging.StreamHandler(sys.stdout)handler.setFormatter(JournalFormatter(\"%(message)s\"))logging.basicConfig(level=logging.INFO, handlers=[handler])<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0412\u0440\u0435\u043c\u044f \u0438 \u0438\u043c\u044f \u0445\u043e\u0441\u0442\u0430 \u0432\u00a0\u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u00a0\u043d\u0443\u0436\u043d\u043e, journald \u043f\u0438\u0448\u0435\u0442 \u0438\u0445 \u0441\u0430\u043c. \u0421\u0430\u043c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u0432\u00a0\u0436\u0443\u0440\u043d\u0430\u043b\u0435 \u043d\u0435\u00a0\u0432\u0438\u0434\u0435\u043d: <code>log.error(\"...\")<\/code> \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0442\u0443\u0434\u0430 \u043a\u0430\u043a\u00a0\u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u043d\u043e\u00a0\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <code>-p err<\/code>.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0436\u0443\u0440\u043d\u0430\u043b \u043d\u0435\u00a0\u0441\u044a\u0435\u043b \u0434\u0438\u0441\u043a \u0438 \u043f\u0435\u0440\u0435\u0436\u0438\u043b \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443, \u0432 <code>\/etc\/systemd\/journald.conf<\/code> \u044f \u0441\u0442\u0430\u0432\u043b\u044e:<\/p>\n<pre><code class=\"ini\">[Journal]Storage=persistentSystemMaxUse=500M<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0438 \u0434\u0435\u043b\u0430\u044e <code>sudo systemctl restart systemd-journald<\/code>.<\/p>\n<h3>\u0410\u043b\u0435\u0440\u0442 \u0432\u00a0Telegram, \u043a\u043e\u0433\u0434\u0430 \u0447\u0442\u043e\u2011\u0442\u043e \u0443\u043f\u0430\u043b\u043e<\/h3>\n<p><code>OnFailure=tg-notify@%n.service<\/code> \u0432\u00a0\u044e\u043d\u0438\u0442\u0435 \u0432\u044b\u0448\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442: \u0435\u0441\u043b\u0438 myapp \u043f\u0435\u0440\u0435\u0448\u0451\u043b \u0432\u00a0\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 failed, \u0437\u0430\u043f\u0443\u0441\u0442\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 <code>tg-notify@myapp.service<\/code>. \u042d\u0442\u043e \u0448\u0430\u0431\u043b\u043e\u043d, <code>%i<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0433\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u0438\u043c\u044f \u0443\u043f\u0430\u0432\u0448\u0435\u0433\u043e \u044e\u043d\u0438\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0434\u0438\u043d \u0448\u0430\u0431\u043b\u043e\u043d \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430\u00a0\u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n<p><code>\/etc\/systemd\/system\/tg-notify@.service<\/code>:<\/p>\n<pre><code class=\"ini\">[Unit]Description=Telegram alert for %i[Service]Type=oneshotEnvironmentFile=\/etc\/tg-notify.envExecStart=\/usr\/local\/bin\/tg-notify %i<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>\/usr\/local\/bin\/tg-notify<\/code>, \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430:<\/p>\n<pre><code class=\"python\">#!\/usr\/bin\/env python3\"\"\"\u0428\u043b\u0451\u0442 \u0432 Telegram \u0438\u043c\u044f \u0443\u043f\u0430\u0432\u0448\u0435\u0433\u043e \u044e\u043d\u0438\u0442\u0430 \u0438 \u0445\u0432\u043e\u0441\u0442 \u0435\u0433\u043e \u043b\u043e\u0433\u043e\u0432.\"\"\"import osimport socketimport subprocessimport sysimport urllib.parseimport urllib.requestunit = sys.argv[1]logs = subprocess.run(    [\"journalctl\", \"-u\", unit, \"-n\", \"20\", \"--no-pager\", \"-o\", \"cat\"],    capture_output=True, text=True,).stdout# \u043b\u0438\u043c\u0438\u0442 Telegram 4096 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0430\u0441text = f\"\ud83d\udd34 {socket.gethostname()}: {unit} \u0443\u043f\u0430\u043b\\n\\n{logs}\"[:4000]api = os.environ.get(\"TG_API\", \"https:\/\/api.telegram.org\")url = f\"{api}\/bot{os.environ['TG_TOKEN']}\/sendMessage\"data = urllib.parse.urlencode({\"chat_id\": os.environ[\"TG_CHAT_ID\"], \"text\": text}).encode()urllib.request.urlopen(url, data=data, timeout=10)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0412 <code>\/etc\/tg-notify.env<\/code> \u043b\u0435\u0436\u0430\u0442 <code>TG_TOKEN<\/code> \u0438 <code>TG_CHAT_ID<\/code>. \u0422\u043e\u043a\u0435\u043d \u0432\u044b\u0434\u0430\u0451\u0442 @BotFather. \u0427\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c chat_id, \u043d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u0441\u0432\u043e\u0435\u043c\u0443 \u0431\u043e\u0442\u0443 \u043b\u044e\u0431\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438 \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 <code>https:\/\/api.telegram.org\/bot&lt;TOKEN&gt;\/getUpdates<\/code>: \u043d\u0443\u0436\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043b\u0435\u0436\u0438\u0442 \u0432 <code>message.chat.id<\/code>. \u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u0442\u0443 \u043f\u0435\u0440\u0432\u044b\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0438\u043d\u0430\u0447\u0435 \u043e\u043d \u043d\u0435\u00a0\u0441\u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u0430\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0412\u00a0\u0430\u043b\u0435\u0440\u0442 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0442\u0440\u0435\u0439\u0441\u0431\u044d\u043a, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0432\u0438\u0434\u043d\u0430 \u043f\u0440\u044f\u043c\u043e \u0432\u00a0Telegram, \u0431\u0435\u0437\u00a0\u0437\u0430\u0445\u043e\u0434\u0430 \u043d\u0430\u00a0\u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<h4>\u0421\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0443\u0434\u0435\u0442 \u0430\u043b\u0435\u0440\u0442\u043e\u0432<\/h4>\n<p>\u0422\u0443\u0442 \u044f \u043d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430\u00a0\u043d\u0435\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u0443\u044e \u0432\u0435\u0449\u044c. \u0412\u00a0systemd 255\u00a0\u043f\u0440\u0438 <code>Restart=on-failure<\/code> \u0441\u0435\u0440\u0432\u0438\u0441 \u043c\u0435\u0436\u0434\u0443 \u043f\u0430\u0434\u0435\u043d\u0438\u0435\u043c \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 failed, \u0438 <code>OnFailure<\/code> \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 <strong>\u043d\u0430\u00a0\u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u0430\u0434\u0435\u043d\u0438\u0435<\/strong>, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 systemd \u0442\u0443\u0442\u00a0\u0436\u0435 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441. \u042f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b \u044d\u0442\u043e \u043d\u0430\u00a0user\u2011\u044e\u043d\u0438\u0442\u0430\u0445: \u043e\u0434\u043d\u043e \u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u0434\u0430\u0451\u0442 \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0443\u0441\u043a <code>tg-notify<\/code> \u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a, \u0446\u0438\u043a\u043b \u0438\u0437\u00a0\u043f\u044f\u0442\u0438 \u043f\u0430\u0434\u0435\u043d\u0438\u0439 \u0434\u0430\u0451\u0442 \u043f\u044f\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 systemd \u0441\u0434\u0430\u043b\u0441\u044f, \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 <code>[Service]<\/code>:<\/p>\n<pre><code class=\"ini\">RestartMode=direct<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u042d\u0442\u0430 \u043e\u043f\u0446\u0438\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u00a0systemd 254\u00a0(\u0432 Ubuntu 22.04\u00a0\u0441\u0442\u043e\u0438\u0442 249, \u0442\u0430\u043c \u0435\u0451 \u043d\u0435\u0442). \u0421\u00a0\u043d\u0435\u0439 \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u044b\u0435 \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043c\u043e\u043b\u0447\u0430, \u0430\u00a0\u0430\u043b\u0435\u0440\u0442 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043e\u0434\u0438\u043d \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b <code>StartLimitBurst<\/code>. \u042f \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0440\u0435\u0436\u0438\u043c \u043f\u043e\u00a0\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e: \u0441\u043a\u0440\u0438\u043f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0430\u0434\u0430\u0435\u0442 \u0440\u0430\u0437 \u0432\u00a0\u0447\u0430\u0441, \u0442\u043e\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c.<\/p>\n<h3>\u0422\u0430\u0439\u043c\u0435\u0440\u044b \u0432\u043c\u0435\u0441\u0442\u043e cron<\/h3>\n<p>\u0414\u043b\u044f\u00a0\u0437\u0430\u0434\u0430\u0447 \u043f\u043e\u00a0\u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0442\u0430\u0439\u043c\u0435\u0440\u044b systemd. \u0413\u043b\u0430\u0432\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0432\u00a0\u0442\u043e\u043c, \u0447\u0442\u043e <code>OnFailure<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0434\u043b\u044f\u00a0\u043d\u0438\u0445, \u0430\u00a0cron \u043c\u043e\u043b\u0447\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u044b\u0432\u043e\u0434 \u0443\u043f\u0430\u0432\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u00a0\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0447\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0438\u043a\u0442\u043e \u043d\u0435\u00a0\u0447\u0438\u0442\u0430\u0435\u0442.<\/p>\n<p><code>\/etc\/systemd\/system\/myapp-report.service<\/code>:<\/p>\n<pre><code class=\"ini\">[Unit]Description=myapp daily reportOnFailure=tg-notify@%n.service[Service]Type=oneshotUser=myappWorkingDirectory=\/opt\/myappExecStart=\/opt\/myapp\/.venv\/bin\/python report.pyEnvironmentFile=\/etc\/myapp.env<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>\/etc\/systemd\/system\/myapp-report.timer<\/code>:<\/p>\n<pre><code class=\"ini\">[Unit]Description=Run myapp report every weekday[Timer]OnCalendar=Mon..Fri 09:00Persistent=trueRandomizedDelaySec=120[Install]WantedBy=timers.target<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>Persistent=true<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443, \u0435\u0441\u043b\u0438 \u0432 09:00\u00a0\u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u044b\u043b \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d. \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u0439\u043c\u0435\u0440, \u0430\u00a0\u043d\u0435\u00a0\u0441\u0435\u0440\u0432\u0438\u0441: <code>sudo systemctl enable --now myapp-report.timer<\/code>. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>systemd-analyze calendar \"Mon..Fri 09:00\"<\/code>, \u0430\u00a0\u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0441\u0435 \u0442\u0430\u0439\u043c\u0435\u0440\u044b \u0438 \u0432\u0440\u0435\u043c\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u00a0\u2014 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>systemctl list-timers<\/code>.<\/p>\n<h3>\u0427\u0435\u0433\u043e \u044d\u0442\u0430 \u0441\u0445\u0435\u043c\u0430 \u043d\u0435\u00a0\u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0443\u043f\u0430\u043b \u0441\u0430\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0438\u043b\u0438\u00a0\u043f\u0440\u043e\u043f\u0430\u043b\u0430 \u0441\u0435\u0442\u044c, \u0430\u043b\u0435\u0440\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u043c\u0443. \u0414\u043b\u044f\u00a0\u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043d\u0430\u0440\u0443\u0436\u0438: \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0437 \u0432\u00a0\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0438\u043d\u0443\u0442 \u043e\u0442\u043c\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u043a\u0430\u043a\u043e\u043c\u2011\u043d\u0438\u0431\u0443\u0434\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u00ab\u043f\u0443\u043b\u044c\u0441\u0430\u00bb (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, open\u2011source healthchecks, \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0443\u00a0\u0441\u0435\u0431\u044f \u043d\u0430\u00a0\u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435), \u0438 \u0442\u043e\u0442 \u043f\u0438\u0448\u0435\u0442 \u0432\u0430\u043c, \u0435\u0441\u043b\u0438 \u043e\u0442\u043c\u0435\u0442\u043a\u0438 \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u043b\u0438\u0441\u044c. \u0422\u0430\u043a\u0436\u0435 systemd \u043d\u0435\u00a0\u0437\u0430\u043c\u0435\u0442\u0438\u0442, \u0447\u0442\u043e\u00a0\u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430\u0432\u0438\u0441 \u0438 \u043d\u0435\u00a0\u043f\u0430\u0434\u0430\u0435\u0442. \u0414\u043b\u044f\u00a0\u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c <code>WatchdogSec=<\/code> \u0438 <code>sd_notify<\/code>, \u043d\u043e\u00a0\u044d\u0442\u043e \u0442\u0435\u043c\u0430 \u0434\u043b\u044f\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>\u0414\u043b\u044f\u00a0\u043f\u0430\u0440\u044b \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043d\u0430\u00a0\u043e\u0434\u043d\u043e\u043c VPS \u043c\u043d\u0435 \u044d\u0442\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e: \u043f\u0440\u0438\u00a0\u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0432\u0441\u0451 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u043e, \u043b\u043e\u0433\u0438 \u043b\u0435\u0436\u0430\u0442 \u0432\u00a0\u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435, \u0430\u00a0\u043e\u00a0\u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0430\u0434\u0435\u043d\u0438\u0438 systemd \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 <code>tg-notify<\/code>. \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a\u00a0\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u00a0\u0430\u043b\u0435\u0440\u0442\u044b, \u043e\u0442\u043f\u0440\u0430\u0432\u044c\u0442\u0435 \u0441\u0435\u0431\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435: \u0441\u0430\u043c \u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u043b \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0430\u00a0\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0435 Bot API (\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u00a0\u043d\u0451\u043c \u0435\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <code>TG_API<\/code>), \u0430\u00a0\u043d\u0435\u00a0\u043d\u0430\u00a0\u0431\u043e\u0435\u0432\u043e\u043c \u0431\u043e\u0442\u0435.<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1093934\/\">https:\/\/habr.com\/ru\/articles\/1093934\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0423\u00a0\u043c\u0435\u043d\u044f \u043d\u0430\u00a0VPS \u0436\u0438\u0432\u0451\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u043b\u043a\u0438\u0445 Python\u2011\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432: \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443 \u0447\u0442\u043e\u2011\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u00a0\u0443\u0442\u0440\u0430\u043c \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0442\u0447\u0451\u0442. \u0420\u0430\u043d\u044c\u0448\u0435 \u043e\u043d\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438\u0441\u044c \u0447\u0435\u0440\u0435\u0437 nohup python app.py &amp; \u0438\u043b\u0438\u00a0\u0432 screen. \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043e\u00a0\u043f\u0435\u0440\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u043b\u0438\u00a0\u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u043e\u0433\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u041f\u043e\u0442\u043e\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0442\u0438\u0445\u043e \u043b\u0435\u0436\u0438\u0442, \u0430\u00a0\u0443\u0437\u043d\u0430\u0451\u0448\u044c \u043e\u0431\u00a0\u044d\u0442\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u043a\u0442\u043e\u2011\u0442\u043e \u0441\u043f\u0440\u043e\u0441\u0438\u0442, \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u00a0\u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442.\u041d\u0438\u0436\u0435 \u0441\u0445\u0435\u043c\u0430, \u043a\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u044f \u043f\u0440\u0438\u0448\u0451\u043b. \u041e\u043d\u0430 \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u0447\u0435\u0442\u044b\u0440\u0435 \u0444\u0430\u0439\u043b\u0430 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e\u00a0\u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432\u00a0\u043b\u044e\u0431\u043e\u043c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u043c \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u0435: systemd \u0438 journald. Docker, supervisord \u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u043d\u0435\u00a0\u043d\u0443\u0436\u043d\u044b.\u0420\u0430\u0441\u043a\u043b\u0430\u0434\u043a\u0430\/opt\/myapp\/            \u043a\u043e\u0434 \u0438 .venv\/opt\/myapp\/data\/       \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u043f\u0430\u043f\u043a\u0430, \u043a\u0443\u0434\u0430 \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0438\u0448\u0435\u0442\/etc\/myapp.env         \u0441\u0435\u043a\u0440\u0435\u0442\u044b, chmod 600, \u0432\u043b\u0430\u0434\u0435\u043b\u0435\u0446 root\u0421\u043a\u0440\u0438\u043f\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0442\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0431\u0435\u0437\u00a0shell:sudo useradd &#8212;system &#8212;home-dir \/opt\/myapp &#8212;shell \/usr\/sbin\/nologin myappsudo chown -R myapp: \/opt\/myapp\/data\u0424\u0430\u0439\u043b \/etc\/myapp.env \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442\u044c root: systemd \u0447\u0438\u0442\u0430\u0435\u0442 EnvironmentFile \u0441\u0430\u043c, \u0434\u043e\u00a0\u0442\u043e\u0433\u043e \u043a\u0430\u043a\u00a0\u0441\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0421\u0430\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043d\u0435\u00a0\u0441\u043c\u043e\u0436\u0435\u0442, \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.\u0421\u0435\u0440\u0432\u0438\u0441 \u0441\u00a0\u0430\u0432\u0442\u043e\u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c\/etc\/systemd\/system\/myapp.service:[Unit]Description=myapp workerAfter=network-online.targetWants=network-online.targetOnFailure=tg-notify@%n.serviceStartLimitIntervalSec=300StartLimitBurst=5[Service]User=myappWorkingDirectory=\/opt\/myappExecStart=\/opt\/myapp\/.venv\/bin\/python app.pyEnvironmentFile=\/etc\/myapp.envEnvironment=PYTHONUNBUFFERED=1Restart=on-failureRestartSec=5NoNewPrivileges=yesPrivateTmp=yesProtectSystem=strictProtectHome=yesReadWritePaths=\/opt\/myapp\/data[Install]WantedBy=multi-user.target\u0427\u0442\u043e\u00a0\u0437\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e:Restart=on-failure \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u043a\u0440\u0438\u043f\u0442, \u0435\u0441\u043b\u0438 \u043e\u043d \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f \u0441\u00a0\u043d\u0435\u043d\u0443\u043b\u0435\u0432\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0438\u043b\u0438\u00a0\u0435\u0433\u043e \u0443\u0431\u0438\u043b\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u043c. \u0415\u0441\u043b\u0438 \u0432\u044b \u0441\u0430\u043c\u0438 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 systemctl stop, \u043e\u043d \u043d\u0435\u00a0\u043f\u043e\u0434\u043d\u0438\u043c\u0435\u0442\u0441\u044f.StartLimitIntervalSec \u0438 StartLimitBurst \u0441\u0442\u043e\u044f\u0442 \u0432 [Unit], \u0430\u00a0\u043d\u0435\u00a0\u0432 [Service]. \u0415\u0441\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u0443\u043f\u0430\u043b 5\u00a0\u0440\u0430\u0437 \u0437\u0430 5\u00a0\u043c\u0438\u043d\u0443\u0442, systemd \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0451\u0442 \u0435\u0433\u043e \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442 \u0432\u00a0\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 failed. \u0411\u0435\u0437\u00a0\u044d\u0442\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043f\u0442 \u0441\u00a0\u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u0432\u00a0\u043a\u043e\u043d\u0444\u0438\u0433\u0435 \u0431\u0443\u0434\u0435\u0442 \u043a\u0440\u0443\u0442\u0438\u0442\u044c\u0441\u044f \u0432\u00a0\u0446\u0438\u043a\u043b\u0435 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e.PYTHONUNBUFFERED=1 \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b print \u0438 \u043b\u043e\u0433\u0438 \u043f\u043e\u043f\u0430\u0434\u0430\u043b\u0438 \u0432\u00a0\u0436\u0443\u0440\u043d\u0430\u043b \u0441\u0440\u0430\u0437\u0443, \u0430\u00a0\u043d\u0435\u00a0\u043f\u0430\u0447\u043a\u043e\u0439 \u043f\u0440\u0438\u00a0\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438.\u0411\u043b\u043e\u043a \u0438\u0437 ProtectSystem=strict \u0438 \u0441\u043e\u0441\u0435\u0434\u0435\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 \u0444\u0430\u0439\u043b\u043e\u0432\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 read\u2011only \u0434\u043b\u044f\u00a0\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u043a\u0440\u043e\u043c\u0435 ReadWritePaths. \u0414\u043b\u044f\u00a0\u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u043e\u0434\u0438\u0442 \u0432\u00a0\u0447\u0443\u0436\u0438\u0435 API, \u044d\u0442\u043e \u0434\u0435\u0448\u0451\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u0445\u043e\u0432\u043a\u0430.\u0417\u0430\u043f\u0443\u0441\u043a \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430:sudo systemctl daemon-reloadsudo systemctl enable &#8212;now myappsystemctl status myapp\u0427\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u00a0\u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0443\u0431\u0435\u0439\u0442\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441: sudo systemctl kill -s KILL myapp. \u0427\u0435\u0440\u0435\u0437 5\u00a0\u0441\u0435\u043a\u0443\u043d\u0434 systemctl status \u0441\u043d\u043e\u0432\u0430 \u043f\u043e\u043a\u0430\u0436\u0435\u0442 active, \u0430 systemctl show myapp -p NRestarts \u0432\u0435\u0440\u043d\u0451\u0442 1.\u041b\u043e\u0433\u0438: \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0448\u0438\u0442\u0435 \u0432\u00a0stdout\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043b\u043e\u0433\u2011\u0444\u0430\u0439\u043b\u044b \u0441\u00a0\u0440\u043e\u0442\u0430\u0446\u0438\u0435\u0439 \u043d\u0435\u00a0\u043d\u0443\u0436\u043d\u044b. \u0412\u0441\u0451, \u0447\u0442\u043e\u00a0\u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0438\u0448\u0435\u0442 \u0432\u00a0stdout \u0438 stderr, \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432\u00a0journald \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u00a0\u0442\u0440\u0435\u0439\u0441\u0431\u044d\u043a\u0430\u043c\u0438. \u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:journalctl -u myapp -f                   # \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438journalctl -u myapp &#8212;since &#171;1 hour ago&#187;journalctl -u myapp -p err               # \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0448\u0438\u0431\u043a\u0438journalctl &#8212;disk-usage\u0427\u0442\u043e\u0431\u044b -p err \u0440\u0430\u0431\u043e\u0442\u0430\u043b, journald \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u043d\u0430\u0442\u044c \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u0442\u0440\u043e\u043a\u0438. \u041e\u043d \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u0432\u0438\u0434\u0430 &lt;3&gt; \u0432\u00a0\u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 (\u044d\u0442\u043e \u0443\u0440\u043e\u0432\u043d\u0438 syslog), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0442\u0435\u0440\u0430:import loggingimport sysclass JournalFormatter(logging.Formatter):    &#171;&#187;&#187;\u041f\u0440\u0435\u0444\u0438\u043a\u0441 &lt;N&gt; journald \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0437\u0430\u043f\u0438\u0441\u0438.&#187;&#187;&#187;    PRIORITY = {logging.DEBUG: 7, logging.INFO: 6, logging.WARNING: 4,                logging.ERROR: 3, logging.CRITICAL: 2}    def format(self, record):        prio = self.PRIORITY.get(record.levelno, 6)        return f&#187;&lt;{prio}&gt;{record.name}: {super().format(record)}&#187;handler = logging.StreamHandler(sys.stdout)handler.setFormatter(JournalFormatter(&#171;%(message)s&#187;))logging.basicConfig(level=logging.INFO, handlers=[handler])\u0412\u0440\u0435\u043c\u044f \u0438 \u0438\u043c\u044f \u0445\u043e\u0441\u0442\u0430 \u0432\u00a0\u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u00a0\u043d\u0443\u0436\u043d\u043e, journald \u043f\u0438\u0448\u0435\u0442 \u0438\u0445 \u0441\u0430\u043c. \u0421\u0430\u043c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u0432\u00a0\u0436\u0443\u0440\u043d\u0430\u043b\u0435 \u043d\u0435\u00a0\u0432\u0438\u0434\u0435\u043d: log.error(&#171;&#8230;&#187;) \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0442\u0443\u0434\u0430 \u043a\u0430\u043a\u00a0\u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u043d\u043e\u00a0\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 -p err.\u0427\u0442\u043e\u0431\u044b \u0436\u0443\u0440\u043d\u0430\u043b \u043d\u0435\u00a0\u0441\u044a\u0435\u043b \u0434\u0438\u0441\u043a \u0438 \u043f\u0435\u0440\u0435\u0436\u0438\u043b \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443, \u0432 \/etc\/systemd\/journald.conf \u044f \u0441\u0442\u0430\u0432\u043b\u044e:[Journal]Storage=persistentSystemMaxUse=500M\u0438 \u0434\u0435\u043b\u0430\u044e sudo systemctl restart systemd-journald.\u0410\u043b\u0435\u0440\u0442 \u0432\u00a0Telegram, \u043a\u043e\u0433\u0434\u0430 \u0447\u0442\u043e\u2011\u0442\u043e \u0443\u043f\u0430\u043b\u043eOnFailure=tg-notify@%n.service \u0432\u00a0\u044e\u043d\u0438\u0442\u0435 \u0432\u044b\u0448\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442: \u0435\u0441\u043b\u0438 myapp \u043f\u0435\u0440\u0435\u0448\u0451\u043b \u0432\u00a0\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 failed, \u0437\u0430\u043f\u0443\u0441\u0442\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 tg-notify@myapp.service. \u042d\u0442\u043e \u0448\u0430\u0431\u043b\u043e\u043d, %i \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0433\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u0438\u043c\u044f \u0443\u043f\u0430\u0432\u0448\u0435\u0433\u043e \u044e\u043d\u0438\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0434\u0438\u043d \u0448\u0430\u0431\u043b\u043e\u043d \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u043d\u0430\u00a0\u0441\u0435\u0440\u0432\u0435\u0440\u0435.\/etc\/systemd\/system\/tg-notify@.service:[Unit]Description=Telegram alert for %i[Service]Type=oneshotEnvironmentFile=\/etc\/tg-notify.envExecStart=\/usr\/local\/bin\/tg-notify %i\/usr\/local\/bin\/tg-notify, \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430:#!\/usr\/bin\/env python3&#8243;&#187;&#187;\u0428\u043b\u0451\u0442 \u0432 Telegram \u0438\u043c\u044f \u0443\u043f\u0430\u0432\u0448\u0435\u0433\u043e \u044e\u043d\u0438\u0442\u0430 \u0438 \u0445\u0432\u043e\u0441\u0442 \u0435\u0433\u043e \u043b\u043e\u0433\u043e\u0432.&#187;&#187;&#187;import osimport socketimport subprocessimport sysimport urllib.parseimport urllib.requestunit = sys.argv[1]logs = subprocess.run(    [&#171;journalctl&#187;, &#171;-u&#187;, unit, &#171;-n&#187;, &#171;20&#187;, &#171;&#8212;no-pager&#187;, &#171;-o&#187;, &#171;cat&#187;],    capture_output=True, text=True,).stdout# \u043b\u0438\u043c\u0438\u0442 Telegram 4096 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0430\u0441text = f&#187;\ud83d\udd34 {socket.gethostname()}: {unit} \u0443\u043f\u0430\u043b\\n\\n{logs}&#187;[:4000]api = os.environ.get(&#171;TG_API&#187;, &#171;https:\/\/api.telegram.org&#187;)url = f&#187;{api}\/bot{os.environ[&#8216;TG_TOKEN&#8217;]}\/sendMessage&#187;data = urllib.parse.urlencode({&#171;chat_id&#187;: os.environ[&#171;TG_CHAT_ID&#187;], &#171;text&#187;: text}).encode()urllib.request.urlopen(url, data=data, timeout=10)\u0412 \/etc\/tg-notify.env \u043b\u0435\u0436\u0430\u0442 TG_TOKEN \u0438 TG_CHAT_ID. \u0422\u043e\u043a\u0435\u043d \u0432\u044b\u0434\u0430\u0451\u0442 @BotFather. \u0427\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c chat_id, \u043d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u0441\u0432\u043e\u0435\u043c\u0443 \u0431\u043e\u0442\u0443 \u043b\u044e\u0431\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438 \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 https:\/\/api.telegram.org\/bot&lt;TOKEN&gt;\/getUpdates: \u043d\u0443\u0436\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043b\u0435\u0436\u0438\u0442 \u0432 message.chat.id. \u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u0442\u0443 \u043f\u0435\u0440\u0432\u044b\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0438\u043d\u0430\u0447\u0435 \u043e\u043d \u043d\u0435\u00a0\u0441\u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u0430\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435.\u0412\u00a0\u0430\u043b\u0435\u0440\u0442 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0442\u0440\u0435\u0439\u0441\u0431\u044d\u043a, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0432\u0438\u0434\u043d\u0430 \u043f\u0440\u044f\u043c\u043e \u0432\u00a0Telegram, \u0431\u0435\u0437\u00a0\u0437\u0430\u0445\u043e\u0434\u0430 \u043d\u0430\u00a0\u0441\u0435\u0440\u0432\u0435\u0440.\u0421\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0443\u0434\u0435\u0442 \u0430\u043b\u0435\u0440\u0442\u043e\u0432\u0422\u0443\u0442 \u044f \u043d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430\u00a0\u043d\u0435\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u0443\u044e \u0432\u0435\u0449\u044c. \u0412\u00a0systemd 255\u00a0\u043f\u0440\u0438 Restart=on-failure \u0441\u0435\u0440\u0432\u0438\u0441 \u043c\u0435\u0436\u0434\u0443 \u043f\u0430\u0434\u0435\u043d\u0438\u0435\u043c \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 failed, \u0438 OnFailure \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u00a0\u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u0430\u0434\u0435\u043d\u0438\u0435, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 systemd \u0442\u0443\u0442\u00a0\u0436\u0435 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441. \u042f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b \u044d\u0442\u043e \u043d\u0430\u00a0user\u2011\u044e\u043d\u0438\u0442\u0430\u0445: \u043e\u0434\u043d\u043e \u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u0434\u0430\u0451\u0442 \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0443\u0441\u043a tg-notify \u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a, \u0446\u0438\u043a\u043b \u0438\u0437\u00a0\u043f\u044f\u0442\u0438 \u043f\u0430\u0434\u0435\u043d\u0438\u0439 \u0434\u0430\u0451\u0442 \u043f\u044f\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432.\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 systemd \u0441\u0434\u0430\u043b\u0441\u044f, \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 [Service]:RestartMode=direct\u042d\u0442\u0430 \u043e\u043f\u0446\u0438\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u00a0systemd 254\u00a0(\u0432 Ubuntu 22.04\u00a0\u0441\u0442\u043e\u0438\u0442 249, \u0442\u0430\u043c \u0435\u0451 \u043d\u0435\u0442). \u0421\u00a0\u043d\u0435\u0439 \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u044b\u0435 \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043c\u043e\u043b\u0447\u0430, \u0430\u00a0\u0430\u043b\u0435\u0440\u0442 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043e\u0434\u0438\u043d \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b StartLimitBurst. \u042f \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0440\u0435\u0436\u0438\u043c \u043f\u043e\u00a0\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e: \u0441\u043a\u0440\u0438\u043f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0430\u0434\u0430\u0435\u0442 \u0440\u0430\u0437 \u0432\u00a0\u0447\u0430\u0441, \u0442\u043e\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c.\u0422\u0430\u0439\u043c\u0435\u0440\u044b \u0432\u043c\u0435\u0441\u0442\u043e cron\u0414\u043b\u044f\u00a0\u0437\u0430\u0434\u0430\u0447 \u043f\u043e\u00a0\u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0442\u0430\u0439\u043c\u0435\u0440\u044b systemd. \u0413\u043b\u0430\u0432\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0432\u00a0\u0442\u043e\u043c, \u0447\u0442\u043e OnFailure \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0434\u043b\u044f\u00a0\u043d\u0438\u0445, \u0430\u00a0cron \u043c\u043e\u043b\u0447\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u044b\u0432\u043e\u0434 \u0443\u043f\u0430\u0432\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u00a0\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0447\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0438\u043a\u0442\u043e \u043d\u0435\u00a0\u0447\u0438\u0442\u0430\u0435\u0442.\/etc\/systemd\/system\/myapp-report.service:[Unit]Description=myapp daily reportOnFailure=tg-notify@%n.service[Service]Type=oneshotUser=myappWorkingDirectory=\/opt\/myappExecStart=\/opt\/myapp\/.venv\/bin\/python report.pyEnvironmentFile=\/etc\/myapp.env\/etc\/systemd\/system\/myapp-report.timer:[Unit]Description=Run myapp report every weekday[Timer]OnCalendar=Mon..Fri 09:00Persistent=trueRandomizedDelaySec=120[Install]WantedBy=timers.targetPersistent=true \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443, \u0435\u0441\u043b\u0438 \u0432 09:00\u00a0\u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u044b\u043b \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d. \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u0439\u043c\u0435\u0440, \u0430\u00a0\u043d\u0435\u00a0\u0441\u0435\u0440\u0432\u0438\u0441: sudo systemctl enable &#8212;now myapp-report.timer. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 systemd-analyze calendar &#171;Mon..Fri 09:00&#187;, \u0430\u00a0\u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0441\u0435 \u0442\u0430\u0439\u043c\u0435\u0440\u044b \u0438 \u0432\u0440\u0435\u043c\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u00a0\u2014 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 systemctl list-timers.\u0427\u0435\u0433\u043e \u044d\u0442\u0430 \u0441\u0445\u0435\u043c\u0430 \u043d\u0435\u00a0\u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0415\u0441\u043b\u0438 \u0443\u043f\u0430\u043b \u0441\u0430\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0438\u043b\u0438\u00a0\u043f\u0440\u043e\u043f\u0430\u043b\u0430 \u0441\u0435\u0442\u044c, \u0430\u043b\u0435\u0440\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u043c\u0443. \u0414\u043b\u044f\u00a0\u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043d\u0430\u0440\u0443\u0436\u0438: \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0437 \u0432\u00a0\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0438\u043d\u0443\u0442 \u043e\u0442\u043c\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u043a\u0430\u043a\u043e\u043c\u2011\u043d\u0438\u0431\u0443\u0434\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u00ab\u043f\u0443\u043b\u044c\u0441\u0430\u00bb (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, open\u2011source healthchecks, \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0443\u00a0\u0441\u0435\u0431\u044f \u043d\u0430\u00a0\u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435), \u0438 \u0442\u043e\u0442 \u043f\u0438\u0448\u0435\u0442 \u0432\u0430\u043c, \u0435\u0441\u043b\u0438 \u043e\u0442\u043c\u0435\u0442\u043a\u0438 \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u043b\u0438\u0441\u044c. \u0422\u0430\u043a\u0436\u0435 systemd \u043d\u0435\u00a0\u0437\u0430\u043c\u0435\u0442\u0438\u0442, \u0447\u0442\u043e\u00a0\u0441\u043a\u0440\u0438\u043f\u0442 \u0437\u0430\u0432\u0438\u0441 \u0438 \u043d\u0435\u00a0\u043f\u0430\u0434\u0430\u0435\u0442. \u0414\u043b\u044f\u00a0\u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c WatchdogSec= \u0438 sd_notify, \u043d\u043e\u00a0\u044d\u0442\u043e \u0442\u0435\u043c\u0430 \u0434\u043b\u044f\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.\u0414\u043b\u044f\u00a0\u043f\u0430\u0440\u044b \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043d\u0430\u00a0\u043e\u0434\u043d\u043e\u043c VPS \u043c\u043d\u0435 \u044d\u0442\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e: \u043f\u0440\u0438\u00a0\u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0432\u0441\u0451 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u043e, \u043b\u043e\u0433\u0438 \u043b\u0435\u0436\u0430\u0442 \u0432\u00a0\u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435, \u0430\u00a0\u043e\u00a0\u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0430\u0434\u0435\u043d\u0438\u0438 systemd \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 tg-notify. \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a\u00a0\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u00a0\u0430\u043b\u0435\u0440\u0442\u044b, \u043e\u0442\u043f\u0440\u0430\u0432\u044c\u0442\u0435 \u0441\u0435\u0431\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435: \u0441\u0430\u043c \u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u043b \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0430\u00a0\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0435 Bot API (\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u00a0\u043d\u0451\u043c \u0435\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f TG_API), \u0430\u00a0\u043d\u0435\u00a0\u043d\u0430\u00a0\u0431\u043e\u0435\u0432\u043e\u043c \u0431\u043e\u0442\u0435.\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 https:\/\/habr.com\/ru\/articles\/1093934\/<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-498492","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/498492","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=498492"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/498492\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=498492"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=498492"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=498492"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}