系统化的交互式脚本和计时器


引言


在Linux上进行开发时,存在创建交互式脚本的任务,这些脚本在系统打开或关闭时执行。 在系统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-target,系统在启动时应该到达该目标。 在启动过程中,systemd将检查依赖项并运行您需要的一切。
有几种方法可以选择final.target,为此我使用了bootloader选项。


最终的发布如下:


  1. 引导程序启动
  2. 引导加载程序通过传递final.target参数来启动固件
  3. Systemd开始系统启动。 它从basic.target到它们的依赖项(例如multi-user.target)依次进入installer.target或work.target。 后者并导致系统以所需的模式工作

准备启动固件


创建固件时,始终需要在启动时恢复系统状态并在关闭电源时保存系统状态。 状态表示配置文件,数据库转储,接口设置等。


Systemd在一个目标中并行启动该过程。 有一些依赖关系可以让您确定脚本执行的顺序。


它如何在我的项目中工作( https://habr.com/en/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,它显示有问题(邀请进入控制台)
  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选项创建oneshot服务,但这会阻止创建交互式脚本。


但是事实是,由ExecOnStop选项启动的命令是在TTY之外执行的! 检查很简单-插入tty命令并保存其输出。


因此,我通过目标实现了关机。 我不假装是100%正确的,但是可以!
如何完成(一般而言):
创建了目标my_shutdown.target,该目标不依赖任何人:
my_shutdown.target


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

当切换到该目标时(通过systemctl隔离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文件。 您不能使用参数调用目标。 您只能服务。


但是我使用target来具有工作灵活性和有保证的动作顺序。


但是,最有趣的是后来。 机器必须关闭/重新启动。 共有2个选项:


  • 用您自己的脚本替换reboot,shutdown和其他命令(在systemctl上它们仍然是符号链接),在脚本内,转到my_shutdown.target。 然后目标内的脚本将直接调用systemctl,例如systemctl reboot
  • 比较简单,但我不喜欢该选项。 在所有接口中,请勿调用shutdown / reboot / others,而应直接调用目标系统。ctl孤立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 

Source: https://habr.com/ru/post/zh-CN478846/


All Articles