summaryrefslogtreecommitdiff
path: root/LINUX/SYSTEMCTL.md
blob: e550eed4f853f1471753356c1bf44f5229a88968 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
Почему стоит перейти на ==`systemd`== вместо скриптов:
- Более надёжная демонизация.
- Автоматический перезапуск при падении.
- Логи сохраняются через journalctl.
- Возможность ограничения ресурсов (CPU, память).
- Красивое управление (`start`, stop, restart, `status`).

#### ▪️ Правильный systemd-юнит для сервиса:
vim /etc/systemd/system/myapp.service:
```sh
[Unit]
Description=MyApp Server
After=network.target

[Service]
Type=simple
ExecStart=/opt/myapp/server
Restart=always
RestartSec=5
WorkingDirectory=/opt/myapp/
StandardOutput=append:/var/log/myapp/server.log  # Каталог и файл должны существовать!!!
StandardError=append:/var/log/myapp/server_error.log  # Каталог и файл должны существовать!!!
User=appuser
Group=appuser
Environment=ENV=production

[Install]
WantedBy=multi-user.target
```
▪️ Что важно здесь:
- Restart=always — перезапуск при сбоях.
- StandardOutput и StandardError перенаправляют логи прямо в файлы.
- User и Group указывают, под кем должен работать процесс.
- WorkingDirectory задаёт рабочую папку для приложения.

▪️ Как активировать сервис:
```sh
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp
```
▪️ Теперь управление сервисом становится надёжным и простым.
▪️ Дополнительные вопросы на собеседовании:
▪️ Вывод:
Переход от скриптов к systemd — это шаг к профессиональной эксплуатации Linux-приложений.  
Меньше ручных ошибок, лучшее управление процессами, больше надёжности.
```sh
# Проверить, включен ли автозапуск сервиса
systemctl is-enabled your_service.service

# Посмотреть статус сервиса (включая последние ошибки)
systemctl status your_service.service

# Включить автозапуск
sudo systemctl enable your_service.service

# Логи сервиса с момента последнего запуска
journalctl -u your_service.service -b

# Показать ошибки systemd на загрузке
systemd-analyze blame
```
🟢 systemctl — управление сервисами и проверка их состояния
🟢 journalctl — просмотр логов systemd
🟢 systemd-analyze помогает понять, что тормозит загрузку системы.

#========================
_bot.service_
```sh
# Создаем НОВУЮ службу или редактируем первоисточник:
sudo systemctl edit --force --full bot

# или редактируем уже имеющуюся (открывается пустой файл 
# для добавления или исправления):
sudo systemctl edit bot

# Все сервисы находятся в:
cd /etc/systemd/system/
#============================
```

```shell
[Unit]
Description=bot
After=network.target # только после запуска сети
# After=multi-user.target

[Service]
Type=simple
ExecStart=python3 /home/vlapa/folder/bot.py
WorkingDirectory=/home/vlapa
Restart=always # on-failure
#----------------------------
User=root
Group=root
#----------------------------

[Install]
WantedBy=multi-user.target # default.target
```

```sh
# перезагрузка всех служб:
sudo systemctl daemon-reload

# включить в автозагрузку:
sudo systemctl enable bot.service

# перезапуск с перечитыванием конфигов
systemctl restart bot.service 

# перезапуск без перечитывания конфигов
systemctl reload bot.service 

# включить в автозагрузку
systemctl enable bot.service 

# выключить из автозагрузки
systemctl disable bot.service 

# проверка включена или нет в автозагрузку
systemctl is-enabled ssh 

# Все модули:
systemctl list-units --all
systemctl list-unit-files --type=service "ssh*"

# Оптимизация загрузки:
systemd-analyze blame

```

```sh
# Создание исполняемого скрипта:
#!/usr/bin/env python3
chmod +x my_script.py

# Запуск скрипта:
./my_script.py
```

===============================
Все модули можно найти в трёх каталогах:

`/usr/lib/systemd/system`
— юниты сервисов, установленных с помощью менеджера пакетов. Самый простой пример — веб-серверы: Apache или Nginx.
`/run/systemd/system`
— юниты, которые создаются в процессе работы системы.
`/etc/systemd/system`
— юниты, которые создаёт администратор системы.

Список всех запущенных модулей можно посмотреть, использовуя команду `systemctl`. В терминале вы увидите таблицу со статусом каждой службы. Разберём, что означает каждый из столбцов:

1. **UNIT**. Название модуля
2. **LOAD**. Статус загрузки конфигурации, если успешно — loaded.
3. **ACTIVE**. Статус службы. Один из следующих: _active, inactive, running, exited, dead, loaded, not-found, plugged, mounted, waiting, listening._
4. **SUB**. Детальная информация о юните.
5. **DESCRIPTION**. Краткое описание модуля — за что он отвечает.

Чтобы увидеть все модули, независимо от того, запущены они или нет, воспользуйтесь командой `systemctl list-units --all`. Вы увидите все модули, которые когда-либо загружал или пытался загрузить диспетчер systemd. Для отображения конкретных записей используйте флаг `--state`. Так, например, для того, чтобы увидеть все неактивные юниты, нужно использовать:

`sudo systemctl list-units --all --state=inactive` ``

### Типы юнитов

Модули делятся на категории по типу. Тип каждого модуля можно узнать из названия файла — он указан через точку. Все типы модулей:

1. .service — описывает, как управлять службой и приложением
2. .socket — описывает сетевой буфер, который используется для активации сокета
3. .device — описывает устройство как необходимое для управления systemd
4. .mount — определяет точку монтирования в системе
5. .automount — настраивает автоматическую установку точки монтирования
6. .swap — описывает пространство подкачки в системе
7. .target — обеспечивает синхронизацию устройств при загрузке системы
8. .path — определяет путь, который используется для активации
9. .timer — определяет задержку или активацию по плану
10. .snapshot — делает снимок системы для последующего восстановления
11. .slice — ограничивает узлы группы управления
12. .scope — systemd создаёт эти модули автоматически, пользуясь информацией из интерфейса шины

```sh
[Unit]
Description=OpenSSH server daemon 
Documentation=man:sshd(8) man:sshd_config(5) 
After=network.target sshd-keygen.target 
Wants=sshd-keygen.target 

[Service]
Type=notify Environment
File=-/etc/crypto-policies/back-ends/opensshserver.config EnvironmentFile=-/etc/sysconfig/sshd 
ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target
```

**Unit**

Это первая обязательная секция. В ней описаны правила взаимодействия с другими службами и указаны метаданные — описание и документация. Подробнее:

- Description — описание модуля.
- Documentation — страница руководства man.
- After — после каких демонов и событий нужно запускать модуль. Например, модули веб-серверов запускаются только после сетевых интерфейсов.
- Requires — сервисы, необходимые для работы юнита
- Wants — сервисы, которые желательно запустить перед стартом модуля

**Service**

В этой секции необходимо указать, какими командами запускать службу:

- Type — как запускается демон? По умолчанию — simple, то есть служба просто запускается. Notify это примерно то же самое, но в таком случае процесс сообщит диспетчеру, что он готов к работе. Есть также типы forking (после запуска демона родительский процесс завершается) и one-shot (выполняется один раз).
- PIDFile — ссылка на основной процесс
- WorkingDirectory — текущая рабочая директория для запуска команд
- User — пользователь для запуска сервиса
- Group — группа для запуска сервиса
- ExecStart — команда для запуска сервиса
- ExecStop — команда для остановки сервиса
- TimeoutSec — время, которое служба ожидает остановки или старта
- Restart — настройки перезапуска

**Install**

В этой секции нужно указать, на каком уровне загрузки системы нужно запускать сервис. Переменная WantedBy сообщает, как включится устройство, в качестве параметра указываются специальные файлы целей. Они служат для того, чтобы привести систему в разные состояния. 

Список доступных целей вы можете получить, выполнив команду 

`sudo systemctl list-unit-files --type=target`


### Редактирование модулей

Модули нельзя править напрямую. Для этого нужно использовать команду 

`systemctl edit`

Откроется файл, который можно использовать для переопределения директив службы или добавления новых. При этом настройки из файла переопределения приоритетнее, чем настройки по умолчанию. 

Если нужно отредактировать файл модуля целиком, а не добавлять новые директивы, нужно использовать флаг `--full`:

`sudo systemctl edit --full apache2.service` ``
  
Перед вами откроется редактор, в котором вы можете править настройки юнита. 

По умолчанию файлы переопределения хранятся в 

`/etc/systemd/system/`

в каталоге который называется так же, как модуль, но с суффиксом `.d`. Например, в случае apache2 это будет директория 

`/etc/systemd/system/apache2.service.d/`. 

Если вы редактируете конфигурацию напрямую с использованием флага `--full`, нужный файл находится в каталоге 

`/etc/systemd/system/`

и называется так же, как модуль.

Для того, чтобы удалить переопределения, которые вы добавили, просто удалите каталог с суффиксом `.d`. Если нужно восстановить настройки по умолчанию, удалите весь файл модуля. В случае с apache2 это:

`sudo rm -r /etc/systemd/system/apache2.service.d` ``
или 
`sudo rm /etc/systemd/system/apache2.service` ``
  
После этого нужно перезагрузить процесс systemd:

`sudo systemctl daemon-reload` `

===============================

## Создание сервиса

В подсистеме systemd также можно легко создать собственную службу и использовать ее для автозапуска приложений или собственных скриптов. Для этого в каталоге **/usr/lib/systemd/system** создаем юнит (файл) с расширением **.service**.

Пример простой и частоиспользуемой конфигурации:

[Unit]  
Description=Service Name  
After=network.target  
  
[Service]  
User=root  
Group=root  
Type=simple  
  
ExecStart=/usr/bin/myapp  
ExecReload=/bin/kill -HUP $MAINPID  
Restart=on-failure  
  
[Install]  
WantedBy=multi-user.target

* как правило, файл разделен на 3 части:

- **Unit** — позволяет определить метаданные для юнита.
- **Service** — раздел для основной конфигурации юнита.
- **Install** — определение поведения для юнита при его включении или отключении.

Подробнее можно почитать о структуре и возможных опциях на странице [https://linux-notes.org/pishem-systemd-unit-fajl/](https://linux-notes.org/pishem-systemd-unit-fajl/)

Более сложный вариант разберем на примере сервиса bind:

vi /usr/lib/systemd/system/named.service

Содержимое может быть следующего содержания:

[Unit]  
Description=Berkeley Internet Name Domain (DNS)  
Wants=nss-lookup.target  
Wants=named-setup-rndc.service  
Before=nss-lookup.target  
After=network.target  
After=named-setup-rndc.service  
  
[Service]  
Type=forking  
Environment=NAMEDCONF=/etc/named.conf  
EnvironmentFile=-/etc/sysconfig/named  
Environment=KRB5_KTNAME=/etc/named.keytab  
PIDFile=/run/named/named.pid  
ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi'  
ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} $OPTIONS  
ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID'  
ExecStop=/bin/sh -c '/usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID'  
PrivateTmp=true  
  
[Install]  
WantedBy=multi-user.target

После внесения изменений и сохранения файла, необходимо перечитать изменения командой:

systemctl daemon-reload

Теперь можно разрешить автозапуск:

systemctl enable named

### Редактирование сервисов

Если мы хотим внести изменения в юнит-файл сервиса, который был установлен с последним, необходимо использовать drop-in файл или файл переопределения настроек. В противном случае, после обновления программы наши изменения могут быть удалены.

И так, мы для примера взяли юнит для bind. Чтобы создать для него drop-in файл, вводим:

systemctl edit named

И вносим, например, такие изменения:

[Service]  
Restart=on-failure

_* будет создан файл **/etc/systemd/system/named.service.d/override.conf**, который будет переопределять настройки основного юнит-файла. В данном примере, мы указываем на необходимость перезапуска сервиса при сбое._

Чтобы убедиться в использовании Drop-In файла смотрим статус сервиса:

systemctl status named

Мы должны увидеть что-то на подобие:

Drop-In: /etc/systemd/system/named.service.d  
           — override.conf

Также мы можем редаетировать файл юните без drop-in. Для этого добавляем опцию full:

systemctl edit --full named

Однако, как было сказано выше, при очередном обновлении приложения, если разработчик пакета предоставляет файл systemd наши изменения могут быть перетерты.

## Таймеры

Выше мы рассмотрели возможность автоматического запуска сервисов с помощью systemd. Мы также можем настроить периодический запуск данных юнитов по таймеру. Для этого нам нужно создать юнит с таким же названием, но на конце должен быть суффикс ==.timer==.

Предположим, мы хотим создать запуск по таймеру named, для которого выше в примере создали юнит сервиса. Тогда создаем файл:

```sh
vi /usr/lib/systemd/system/named.timer

[Unit]  
Description=Run named every 10 min  
  
[Timer]  
OnBootSec=5min  
OnUnitActiveSec=10min  
  
[Install]  
WantedBy=timers.target

# в данном примере наш таймер будет создан для юнита named; он запустится через 5 минут после старта службы и будет запускать ее каждые 10 минут

# Перечитаем изменения в systemd:
systemctl daemon-reload

# Разрешаем наш таймер:
systemctl enable named.timer

# Запустим его:
systemctl start named.timer

# Вывести список таймеров можно командой:
systemctl list-timers
```