介紹
在針對 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 選項。
最終的啟動看起來像這樣:
- 引導程式啟動
- 引導程式透過傳遞 Final.target 參數開始啟動韌體
- Systemd 開始啟動系統。 依序從 basic.target 透過其依賴項(例如,multi-user.target)轉到 installer.target 或 work.target。 後者使系統以所需的模式工作
準備啟動韌體
建立韌體時,總是會出現在啟動時恢復系統狀態並在關閉時保存系統狀態的任務。 狀態意味著設定檔、資料庫轉儲、介面設定等。
Systemd 在同一目標中並行運行進程。 有些依賴項可讓您確定腳本的啟動順序。
它在我的專案中如何運作(
- 系統啟動
- settings_restore.service服務啟動,它檢查資料部分中是否存在settings.txt檔案。 如果不存在,則將參考檔案放在其位置。接下來,恢復系統設定:
- 管理者密碼
- 主機名,
- 時區
- 語言環境
- 確定是否所有媒體都在使用。 預設情況下,影像尺寸較小 - 以便於複製和記錄到媒體。 啟動時,它會檢查是否仍有未使用的空間。 如果有,則對磁碟重新分割。
- 從 MAC 位址產生機器 ID。 這對於透過 DHCP 取得相同的位址很重要
- 網絡設置
- 限制日誌的大小
- 外部驅動器正在準備工作(如果啟用了相應的選項並且驅動器是新的)
- 啟動 postgresq
- 恢復服務啟動。 需要準備zabbix本身及其資料庫:
- 檢查是否已經有zabbix資料庫。 如果沒有,它是從初始化轉儲創建的(包含在 zabbix 中)
- 建立時區清單(需要在 Web 介面中顯示它們)
- 找到目前IP,顯示在issue中(邀請登入控制台)
- 邀請函發生變化 - 出現「準備工作」短語
- 韌體可供使用
服務文件很重要,它們決定了啟動順序
[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