Systemd、互動式腳本和計時器

Systemd、互動式腳本和計時器

介紹

在針對 Linux 進行開發時,會出現建立在系統開啟或關閉時執行的互動式腳本的任務。 在 System V 中這很容易,但在 systemd 中則需要進行調整。 但它可以有自己的計時器。

為什麼我們需要目標?

人們常說目標相當於系統 V -init 中的運作等級。 我從根本上不同意。 它們有更多,您可以將套件分組,例如,使用一個命令啟動一組服務並執行其他操作。 而且,它們沒有層次結構,只有依賴關係。

啟用時執行互動式腳本的目標範例(功能概述)

目標本身的描述:

cat installer.target
[Unit]
Description=My installer
Requires=multi-user.target 
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target 
AllowIsolate=yes
Wants=installer.service

該目標將在 multi-user.target 啟動並呼叫 installer.service 時啟動。 然而,可能有多個這樣的服務。

cat installer.service
[Unit]
# описание
Description=installer interactive dialog

[Service]
# Запустить один раз, когда остальное будет запущенно
Type=idle
# Команда запуска - вызов скрипта
ExecStart=/usr/bin/installer.sh
# Интерактивное взаимодействие с пользователем через tty3
StandardInput=tty
TTYPath=/dev/tty3
TTYReset=yes
TTYVHangup=yes

[Install]
WantedBy=installer.target

最後是正在執行的腳本的範例:

#!/bin/bash
# Переходим в tty3
chvt 3
echo "Install, y/n ?"
read user_answer

最重要的是選擇final.target - 系統啟動時應到達的目標。 在啟動過程中,systemd 將遍歷依賴項並啟動它所需的一切。
有不同的方法來選擇 Final.target,我為此使用了 loader 選項。

最終的啟動看起來像這樣:

  1. 引導程式啟動
  2. 引導程式透過傳遞 Final.target 參數開始啟動韌體
  3. Systemd 開始啟動系統。 依序從 basic.target 透過其依賴項(例如,multi-user.target)轉到 installer.target 或 work.target。 後者使系統以所需的模式工作

準備啟動韌體

建立韌體時,總是會出現在啟動時恢復系統狀態並在關閉時保存系統狀態的任務。 狀態意味著設定檔、資料庫轉儲、介面設定等。

Systemd 在同一目標中並行運行進程。 有些依賴項可讓您確定腳本的啟動順序。

它在我的專案中如何運作( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. 系統啟動
  2. settings_restore.service服務啟動,它檢查資料部分中是否存在settings.txt檔案。 如果不存在,則將參考檔案放在其位置。接下來,恢復系統設定:
    • 管理者密碼
    • 主機名,
    • 時區
    • 語言環境
    • 確定是否所有媒體都在使用。 預設情況下,影像尺寸較小 - 以便於複製和記錄到媒體。 啟動時,它會檢查是否仍有未使用的空間。 如果有,則對磁碟重新分割。
    • 從 MAC 位址產生機器 ID。 這對於透過 DHCP 取得相同的位址很重要
    • 網絡設置
    • 限制日誌的大小
    • 外部驅動器正在準備工作(如果啟用了相應的選項並且驅動器是新的)
  3. 啟動 postgresq
  4. 恢復服務啟動。 需要準備zabbix本身及其資料庫:
    • 檢查是否已經有zabbix資料庫。 如果沒有,它是從初始化轉儲創建的(包含在 zabbix 中)
    • 建立時區清單(需要在 Web 介面中顯示它們)
    • 找到目前IP,顯示在issue中(邀請登入控制台)
  5. 邀請函發生變化 - 出現「準備工作」短語
  6. 韌體可供使用

服務文件很重要,它們決定了啟動順序

[Unit]
Description=restore system settings
Before=network.service prepare.service postgresql.service systemd-networkd.service systemd-resolved.service

[Service]
Type=oneshot
ExecStart=/usr/bin/settings_restore.sh

[Install]
WantedBy=multi-user.target

正如您所看到的,我安裝了依賴項,以便我的腳本首先起作用,然後網路才會啟動並且 DBMS 才會啟動。

以及第二個服務(zabbix準備)

#!/bin/sh
[Unit]
Description=monitor prepare system
After=postgresql.service settings_restore.service
Before=zabbix-server.service zabbix-agent.service

[Service]
Type=oneshot
ExecStart=/usr/bin/prepare.sh

[Install]
WantedBy=multi-user.target

這裡有點複雜。啟動也是在 multi-user.target 中,但在啟動 postgresql DBMS 和我的setting_restore 之後。 但在啟動 zabbix 服務之前。

logrotate 的定時器服務

Systemd 可以取代 CRON。 嚴重地。 而且,精確度不是精確到分鐘,而是精確到秒(如果需要的話怎麼辦)。或者您可以建立一個單調的計時器,由事件的逾時呼叫。
這是一個單調的計時器,從我創建的機器啟動開始計算時間。
這將需要 2 個文件
logrotateTimer.service - 服務的實際描述:

[Unit]
Description=run logrotate

[Service]
ExecStart=logrotate /etc/logrotate.conf
TimeoutSec=300

很簡單 - 啟動指令的描述。
第二個檔案 logrotateTimer.timer 是計時器工作的地方:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

這裡有什麼:

  • 定時器描述
  • 首次啟動時間,從系統啟動開始
  • 進一步推出的時期
  • 對定時器服務的依賴,其實就是這個字串讓定時器

關機時的互動式腳本和您的關機目標

在另一個開發中,我必須透過我自己的目標執行更複雜的關機版本,以便執行許多操作。 通常建議使用 RemainAfterExit 選項建立一次性服務,但這會阻止您建立互動式腳本。

但事實是 ExecOnStop 選項啟動的命令是在 TTY 之外執行的! 檢查很容易 - 貼上 tty 命令並保存其輸出。

因此,我通過我的目標實現了關閉。 我不敢保證 100% 正確,但它確實有效!
它是如何完成的(一般而言):
我創建了一個目標 my_shutdown.target,它不依賴任何人:
my_shutdown.target

[Unit]
Description=my shutdown
AllowIsolate=yes
Wants=my_shutdown.service 

當轉到這個目標時(透過 systemctlisolate my_shutdwn.target),它啟動了 my_shutdown.service 服務,其任務很簡單 - 執行 my_shutdown.sh 腳本:

[Unit]
Description=MY shutdown

[Service]
Type=oneshot
ExecStart=/usr/bin/my_shutdown.sh
StandardInput=tty
TTYPath=/dev/tty3
TTYReset=yes
TTYVHangup=yes

WantedBy=my_shutdown.target

  • 在此腳本中,我執行必要的操作。 為了靈活性和方便性,您可以為目標添加許多腳本:

my_shutdown.sh

#!/bin/bash --login
if [ -f /tmp/reboot ];then
    command="systemctl reboot"
elif [ -f /tmp/shutdown ]; then
    command="systemctl poweroff"
fi
#Вот здесь нужные команды
#Например, cp /home/user/data.txt /storage/user/
    $command

筆記。 使用 /tmp/reboot 和 /tmp/shutdown 檔案。 您不能使用參數呼叫目標。 只有服務是可能的。

但我使用目標是為了在工作上具有彈性和保證的行動順序。

然而,最有趣的事情來了。 機器需要關閉/重新啟動。 並且有 2 個選項:

  • 將reboot、shutdown 和其他命令(它們仍然是systemctl 的符號連結)替換為您的腳本。在腳本內,請前往my_shutdown.target。 然後目標內部的腳本直接呼叫systemctl,例如systemctl restart
  • 一個更簡單的選擇,但我不喜歡它。 所有介面中,不要呼叫shutdown/reboot/other,而是直接呼叫目標systemctlisolate my_shutdown.target

我選擇了第一個選項。 在 systemd 中,重新啟動(如關機)是 systemd 的符號連結。

ls -l /sbin/poweroff 
lrwxrwxrwx 1 root root 14 сен 30 18:23 /sbin/poweroff -> /bin/systemctl

因此,您可以用自己的腳本替換它們:
重啟

#!/bin/sh
    touch /tmp/reboot
    sudo systemctl isolate my_shutdown.target
fi

來源: www.habr.com

添加評論