
Giới thiệu
Khi phát triển cho Linux, nhiệm vụ tạo các tập lệnh tương tác được thực thi khi hệ thống được bật hoặc tắt sẽ phát sinh. Trong hệ thống V, việc này thật dễ dàng, nhưng với systemd, nó sẽ thực hiện các điều chỉnh. Nhưng nó có thể có bộ tính giờ riêng.
Tại sao chúng ta cần mục tiêu?
Người ta thường viết rằng mục tiêu đóng vai trò tương tự như runlevel trong hệ thống V -init. Về cơ bản tôi không đồng ý. Có nhiều gói hơn và bạn có thể chia các gói thành các nhóm, chẳng hạn như khởi chạy một nhóm dịch vụ bằng một lệnh và thực hiện các hành động bổ sung. Hơn nữa, chúng không có thứ bậc, chỉ có sự phụ thuộc.
Ví dụ về mục tiêu khi được bật (tổng quan về tính năng) với tập lệnh tương tác đang chạy
Mô tả về chính mục tiêu:
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.serviceMục tiêu này sẽ bắt đầu khi multi-user.target được khởi chạy và gọi Installer.service. Tuy nhiên, có thể có một số dịch vụ như vậy.
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.targetVà cuối cùng, một ví dụ về tập lệnh đang được thực thi:
#!/bin/bash
# Переходим в tty3
chvt 3
echo "Install, y/n ?"
read user_answerĐiều quan trọng nhất là chọn Final.target - mục tiêu mà hệ thống sẽ hướng tới khi khởi động. Trong quá trình khởi động, systemd sẽ xem xét các phần phụ thuộc và khởi chạy mọi thứ nó cần.
Có nhiều cách khác nhau để chọn Final.target, tôi đã sử dụng tùy chọn trình tải cho việc này.
Lần ra mắt cuối cùng trông như thế này:
- Bộ nạp khởi động bắt đầu
- Bộ nạp khởi động bắt đầu khởi chạy chương trình cơ sở bằng cách truyền tham số Final.target
- Systemd bắt đầu khởi động hệ thống. Tuần tự chuyển đến Installer.target hoặc Work.target từ Basic.target thông qua các phần phụ thuộc của chúng (ví dụ: multi-user.target). Cái sau đưa hệ thống hoạt động ở chế độ mong muốn
Chuẩn bị phần sụn để khởi chạy
Khi tạo chương trình cơ sở, nhiệm vụ luôn đặt ra là khôi phục trạng thái hệ thống khi khởi động và lưu nó khi tắt. Trạng thái có nghĩa là các tệp cấu hình, kết xuất cơ sở dữ liệu, cài đặt giao diện, v.v.
Systemd chạy song song các tiến trình trong cùng một mục tiêu. Có những phần phụ thuộc cho phép bạn xác định trình tự khởi động của tập lệnh.
Nó hoạt động như thế nào trong dự án của tôi ( )
- Hệ thống bắt đầu
- Dịch vụ settings_restore.service được khởi chạy. Nó kiểm tra sự hiện diện của tệp settings.txt trong phần dữ liệu. Nếu nó không có ở đó, thì một tệp tham chiếu sẽ được đặt vào vị trí của nó. Tiếp theo, cài đặt hệ thống sẽ được khôi phục:
- mật khẩu quản trị viên
- tên máy chủ,
- Múi giờ
- ngôn ngữ
- Xác định xem tất cả phương tiện có đang được sử dụng hay không. Theo mặc định, kích thước hình ảnh nhỏ - để dễ sao chép và ghi vào phương tiện. Khi khởi động, nó sẽ kiểm tra xem còn chỗ trống chưa sử dụng hay không. Nếu có, đĩa sẽ được phân vùng lại.
- Tạo id máy từ địa chỉ MAC. Điều này rất quan trọng để có được cùng một địa chỉ thông qua DHCP
- Thiết lạp mạng lưới
- Giới hạn kích thước của nhật ký
- Ổ đĩa ngoài đang được chuẩn bị hoạt động (nếu tùy chọn tương ứng được bật và ổ đĩa mới)
- Bắt đầu postgresq
- Dịch vụ khôi phục bắt đầu. Cần phải chuẩn bị zabbix và cơ sở dữ liệu của nó:
- Kiểm tra xem đã có cơ sở dữ liệu Zabbix chưa. Nếu không, nó sẽ được tạo từ các kết xuất khởi tạo (có trong zabbix)
- một danh sách các múi giờ được tạo (cần thiết để hiển thị chúng trong giao diện web)
- IP hiện tại được tìm thấy, nó được hiển thị có vấn đề (mời đăng nhập vào bảng điều khiển)
- Lời mời thay đổi - xuất hiện cụm từ Sẵn sàng làm việc
- Phần sụn đã sẵn sàng để sử dụng
Các tệp dịch vụ rất quan trọng, chúng là những tệp thiết lập trình tự khởi chạy của chúng
[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.targetNhư bạn có thể thấy, tôi đã cài đặt các phần phụ thuộc để tập lệnh của tôi hoạt động trước tiên và chỉ sau đó mạng mới hoạt động và DBMS mới khởi động.
Và dịch vụ thứ hai (chuẩn bị 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Ở đây phức tạp hơn một chút. Việc khởi chạy cũng diễn ra trong multi-user.target, nhưng SAU KHI khởi động DBMS postgresql và setting_restore của tôi. Nhưng TRƯỚC KHI bắt đầu dịch vụ zabbix.
Dịch vụ hẹn giờ cho logrotate
Systemd có thể thay thế CRON. Nghiêm túc. Hơn nữa, độ chính xác không đến từng phút mà lên đến từng giây (nếu cần). Hoặc bạn có thể tạo một bộ đếm thời gian đơn điệu, được gọi theo thời gian chờ của một sự kiện.
Đó là chiếc đồng hồ đếm thời gian đơn điệu tính từ lúc khởi động chiếc máy mà tôi tạo ra.
Điều này sẽ yêu cầu 2 tập tin
logrotateTimer.service - mô tả thực tế của dịch vụ:
[Unit]
Description=run logrotate
[Service]
ExecStart=logrotate /etc/logrotate.conf
TimeoutSec=300Thật đơn giản - mô tả lệnh khởi chạy.
Tệp thứ hai logrotateTimer.timer là nơi bộ tính giờ hoạt động:
[Unit]
Description=Run logrotate
[Timer]
OnBootSec=15min
OnUnitActiveSec=15min
[Install]
WantedBy=timers.targetCái gì đây:
- mô tả hẹn giờ
- Thời gian khởi động lần đầu tiên, bắt đầu từ lúc khởi động hệ thống
- thời gian ra mắt tiếp theo
- Sự phụ thuộc vào dịch vụ hẹn giờ Trong thực tế, đây là chuỗi tạo nên bộ đếm thời gian.
Tập lệnh tương tác khi tắt và mục tiêu tắt máy của bạn
Trong một quá trình phát triển khác, tôi phải thực hiện một phiên bản tắt máy phức tạp hơn - thông qua mục tiêu của riêng mình, để thực hiện nhiều hành động. Thông thường, bạn nên tạo dịch vụ oneshot với tùy chọn RemainAfterExit, nhưng điều này ngăn bạn tạo tập lệnh tương tác.
Nhưng thực tế là các lệnh được khởi chạy bởi tùy chọn ExecOnStop được thực thi bên ngoài TTY! Thật dễ dàng để kiểm tra - dán lệnh tty và lưu kết quả của nó.
Vì vậy, tôi đã thực hiện việc tắt máy thông qua mục tiêu của mình. Tôi không khẳng định là đúng 100%, nhưng nó hoạt động!
Nó đã được thực hiện như thế nào (nói chung):
Tôi đã tạo mục tiêu my_shutdown.target, mục tiêu này không phụ thuộc vào bất kỳ ai:
my_shutdown.target
[Unit]
Description=my shutdown
AllowIsolate=yes
Wants=my_shutdown.service Khi đi đến mục tiêu này (thông qua systemctl cô lập my_shutdwn.target), nó đã khởi chạy dịch vụ my_shutdown.service, nhiệm vụ của dịch vụ này rất đơn giản - thực thi tập lệnh 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- Bên trong tập lệnh này, tôi thực hiện các hành động cần thiết. Bạn có thể thêm nhiều tập lệnh vào mục tiêu để linh hoạt và thuận tiện:
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/
$commandGhi chú. Sử dụng các tệp /tmp/reboot và /tmp/shutdown. Bạn không thể gọi mục tiêu bằng các tham số. Chỉ có dịch vụ là có thể.
Nhưng tôi sử dụng mục tiêu để có sự linh hoạt trong công việc và thứ tự hành động được đảm bảo.
Tuy nhiên, điều thú vị nhất lại đến sau đó. Máy cần được tắt/khởi động lại. Và có 2 lựa chọn:
- Thay thế các lệnh khởi động lại, tắt máy và các lệnh khác (chúng vẫn là các liên kết tượng trưng đến systemctl) bằng tập lệnh của bạn. Bên trong tập lệnh, hãy truy cập my_shutdown.target. Và các script bên trong target sau đó gọi trực tiếp systemctl, ví dụ: systemctl restart
- Một lựa chọn đơn giản hơn, nhưng tôi không thích nó. Trong tất cả các giao diện, không gọi tắt máy/khởi động lại/khác mà gọi trực tiếp systemctl đích cô lập my_shutdown.target
Tôi đã chọn tùy chọn đầu tiên. Trong systemd, khởi động lại (như tắt nguồn) là các liên kết tượng trưng đến systemd.
ls -l /sbin/poweroff
lrwxrwxrwx 1 root root 14 сен 30 18:23 /sbin/poweroff -> /bin/systemctlDo đó, bạn có thể thay thế chúng bằng tập lệnh của riêng mình:
khởi động lại
#!/bin/sh
touch /tmp/reboot
sudo systemctl isolate my_shutdown.target
fiNguồn: www.habr.com
