当前位置: 首页 > news >正文

为什么我推荐你使用 systemd timer 替代 cronjob?

概述

前几天在使用 Terraform + cloud-init 批量初始化我的实验室 Linux 机器。正好发现有一些定时场景需要使用到 cronjob, 进一步了解到 systemd timer 完全可以替换 cronjob, 并且 systemd timer 有一些非常有趣的功能。

回归话题:为什么我推荐你使用 systemd timer 替代 cronjob? 因为相比 cronjob, systemd timer 有这些优势:

  • 可以覆盖 cronjob 的所有功能
  • 统一日志收集到 systemd 日志
  • 针对时间精确度更详细的配置项
  • 除了定时场景,还支持基于 event 的触发
  • 相比 cronjob 更灵活的语法
  • 更丰富的使用/运维命令集

接下来我们一一介绍。

首先我们通过系统自带的 timer 来熟悉这个新玩意。

系统自带的 timer

当 Ubuntu 或任何基于 systemd 的发行版安装在一个新系统上时,它会创建几个 timer,作为任何 Linux 主机后台的系统维护程序的一部分。这些 timer 会触发普通维护任务所需的事件,比如更新系统数据库、清理临时目录、切割日志文件等等。

我们使用systemctl status *timer命令列出我的主机上的所有 timer:

casey@casey-Virtual-Machine:~$ systemctl status *timer
● plocate-updatedb.timer - Update the plocate database dailyLoaded: loaded (/lib/systemd/system/plocate-updatedb.timer; enabled; vendor preset: enabled)Active: active (waiting) since Tue 2023-04-04 16:49:49 CST; 19s agoTrigger: Wed 2023-04-05 00:40:16 CST; 7h leftTriggers: ● plocate-updatedb.service4 月 04 16:49:49 casey-Virtual-Machine systemd[1]: Started Update the plocate database daily.● fwupd-refresh.timer - Refresh fwupd metadata regularlyLoaded: loaded (/lib/systemd/system/fwupd-refresh.timer; enabled; vendor preset: enabled)Active: active (waiting) since Tue 2023-04-04 16:49:49 CST; 19s agoTrigger: Wed 2023-04-05 01:54:51 CST; 9h leftTriggers: ● fwupd-refresh.service4 月 04 16:49:49 casey-Virtual-Machine systemd[1]: Started Refresh fwupd metadata regularly.● update-notifier-motd.timer - Check to see whether there is a new version of Ubuntu availableLoaded: loaded (/lib/systemd/system/update-notifier-motd.timer; enabled; vendor preset: enabled)Active: active (waiting) since Tue 2023-04-04 16:49:50 CST; 19s agoTrigger: Sat 2023-04-08 03:19:02 CST; 3 days leftTriggers: ● update-notifier-motd.service4 月 04 16:49:50 casey-Virtual-Machine systemd[1]: Started Check to see whether there is a new version of Ubuntu available.● fstrim.timer - Discard unused blocks once a weekLoaded: loaded (/lib/systemd/system/fstrim.timer; enabled; vendor preset: enabled)Active: active (waiting) since Tue 2023-04-04 16:49:49 CST; 19s agoTrigger: Tue 2023-04-04 17:58:23 CST; 1h 8min leftTriggers: ● fstrim.serviceDocs: man:fstrim4 月 04 16:49:49 casey-Virtual-Machine systemd[1]: Started Discard unused blocks once a week.
...

每个 timer 至少有六行信息与之相关:

  • 第一行是 timer 的文件名和对其用途的简短描述。
  • 第二行显示 timer 的状态,它是否被加载,timer unit 文件的完整路径,以及供应商的预设。
  • 第三行显示其活动状态,包括 timer 开始活动的日期和时间。
  • 第四行包含 timer 下次被触发的日期和时间,以及直到触发发生的大致时间。
  • 第五行显示由 timer 触发的事件或服务的名称。
  • 一些(但不是全部)systemd unit 文件有指向相关文档的指针。如上面的 Docs: man:fstrim
  • 最后一行是 timer 所触发的服务的最新实例的日志条目。

创建 timer

优势之一:统一日志收集到 systemd 日志

为了更快了解 timer, 我们创建自己的 service unit 和 timer unit 来触发。

具体用途为:每周定期更新 tailscale 的版本。

首先,创建 tailscale update 服务,如下:

[Unit]
Description=Tailscale update
Wants=tailscale-weekly-update.timer[Service]
Type=oneshot
ExecStart=/usr/bin/tailscale update -yes[Install]
WantedBy=multi-user.target

然后,创建 tailscale update timer, 如下:

[Unit]
Description=Tailscale update
Requires=tailscale-weekly-update.service[Timer]
Unit=tailscale-weekly-update.service
OnCalendar=weekly[Install]
WantedBy=timers.target

最后,启用 timer:

systemctl enable tailscale-weekly-update.timer 

这样就可以了,但是为了演示,执行:systemctl start tailscale-weekly-update.service 手动运行一次。

输出会直接集成到 systemd 日志里,并可以通过 journalctl 查看:(包含手动执行日志,和后续自动定期执行的日志)

$ sudo journalctl -S "2023-03-29 00:00:00" -u tailscale-weekly-update.service
4 月 02 09:14:28 casey-Virtual-Machine systemd[1]: Starting Tailscale node agent...
4 月 02 09:14:30 casey-Virtual-Machine tailscale[6898]: 获取:1 https://pkgs.tailscale.com/stable/ubuntu jammy InRelease
4 月 02 09:14:30 casey-Virtual-Machine tailscale[6898]: 获取:2 https://pkgs.tailscale.com/stable/ubuntu jammy/main amd64 Packages [7,853 B]
4 月 02 09:14:32 casey-Virtual-Machine tailscale[6898]: 已下载 13.9 kB,耗时 1 秒 (14.4 kB/s)
4 月 02 09:14:32 casey-Virtual-Machine tailscale[6898]: 正在读取软件包列表。..
4 月 02 09:14:33 casey-Virtual-Machine tailscale[7101]: 正在读取软件包列表。..
4 月 02 09:14:33 casey-Virtual-Machine tailscale[7101]: 正在分析软件包的依赖关系树。..
4 月 02 09:14:33 casey-Virtual-Machine tailscale[7101]: 正在读取状态信息。..
4 月 02 09:14:33 casey-Virtual-Machine tailscale[7101]: 下列软件包将被升级:
4 月 02 09:14:33 casey-Virtual-Machine tailscale[7101]:   tailscale
4 月 02 09:14:34 casey-Virtual-Machine tailscale[7101]: 升级了 1 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 4 个软件包未被升级。
4 月 02 09:14:34 casey-Virtual-Machine tailscale[7101]: 需要下载 23.0 MB 的归档。
4 月 02 09:14:34 casey-Virtual-Machine tailscale[7101]: 解压缩后将会空出 1,024 B 的空间。
4 月 02 09:14:34 casey-Virtual-Machine tailscale[7101]: 获取:1 https://pkgs.tailscale.com/stable/ubuntu jammy/main amd64 tailscale amd64 1.38.3 [23.0 MB]
4 月 02 09:15:13 casey-Virtual-Machine tailscale[7115]: debconf: 无法初始化前端界面:Dialog
4 月 02 09:15:13 casey-Virtual-Machine tailscale[7115]: debconf: (系统未设定 TERM 环境变量,所以对话框界面将不可使用。)
4 月 02 09:15:13 casey-Virtual-Machine tailscale[7115]: debconf: 返回前端界面:Readline
4 月 02 09:15:13 casey-Virtual-Machine tailscale[7115]: debconf: 无法初始化前端界面:Readline
4 月 02 09:15:13 casey-Virtual-Machine tailscale[7115]: debconf: (这个界面要求可控制的 tty。)
4 月 02 09:15:13 casey-Virtual-Machine tailscale[7115]: debconf: 返回前端界面:Teletype
4 月 02 09:15:13 casey-Virtual-Machine tailscale[7115]: dpkg-preconfigure: 重新开启标准输入失败:
4 月 02 09:15:13 casey-Virtual-Machine tailscale[7101]: 已下载 23.0 MB,耗时 40 秒 (577 kB/s)
4 月 02 09:15:14 casey-Virtual-Machine tailscale[7101]: [729B blob data]
4 月 02 09:15:14 casey-Virtual-Machine tailscale[7101]: 准备解压 .../tailscale_1.38.3_amd64.deb  ...
4 月 02 09:15:14 casey-Virtual-Machine tailscale[7101]: 正在解压 tailscale (1.38.3) 并覆盖 (1.38.2) ...
4 月 02 09:15:15 casey-Virtual-Machine tailscale[7101]: 正在设置 tailscale (1.38.3) ...
4 月 02 09:15:23 casey-Virtual-Machine tailscale[7325]: Running kernel seems to be up-to-date.
4 月 02 09:15:23 casey-Virtual-Machine tailscale[7325]: Services to be restarted:
4 月 02 09:15:23 casey-Virtual-Machine tailscale[7325]:  systemctl restart tailscale-weekly-update.service
4 月 02 09:15:23 casey-Virtual-Machine tailscale[7325]: No containers need to be restarted.
4 月 02 09:15:23 casey-Virtual-Machine tailscale[7325]: No user sessions are running outdated binaries.
4 月 02 09:15:23 casey-Virtual-Machine tailscale[7325]: No VM guests are running outdated hypervisor (qemu) binaries on this host.
4 月 02 09:15:24 casey-Virtual-Machine systemd[1]: tailscale-weekly-update.service: Deactivated successfully.
4 月 02 09:15:24 casey-Virtual-Machine systemd[1]: Finished Tailscale node agent.
4 月 02 09:15:24 casey-Virtual-Machine systemd[1]: tailscale-weekly-update.service: Consumed 6.317s CPU time.$ sudo journalctl -S "2023-03-29 00:00:00" -u tailscale-weekly-update.timer
4 月 02 09:14:28 casey-Virtual-Machine systemd[1]: Started Tailscale node agent.
4 月 02 20:01:52 casey-Virtual-Machine systemd[1]: tailscale-weekly-update.timer: Deactivated successfully.
4 月 02 20:01:52 casey-Virtual-Machine systemd[1]: Stopped Tailscale node agent.

如上面的日志,可以很方便地检查 timer 和服务的状态。

在日志这方面,你不需要做任何特别的事情,就可以使tailscale-weekly-update.service unit 中的ExecStart触发器的STDOUT存储在日志中。这都是使用 systemd 运行服务的一部分。

Systemd timer 时间精度

优势之一:针对时间精确度更详细的配置项

从上面日志,如果细看,timer 不会在:00秒的时候准确触发,甚至不会在上一个实例的一分钟内准确触发。这是故意的,但如果有必要的话,可以覆盖它的默认配置。

这种行为的原因是为了防止多个服务在完全相同的时间被触发。例如,你可以使用时间规格,如每周、每天,等等。这些快捷方式都被定义为在它们被触发的那一天的 00:00:00 时触发。当多个 timer 被这样指定时,它们很有可能会试图同时启动。

systemd timer 被有意设计成在指定时间内随机触发,以防止同时触发。它们在一个时间窗口内半随机地触发。根据systemd.timer手册,这个触发时间相对于所有其他定义的 timer 单位来说,保持在一个稳定的位置。

大多数时候,这种概率性的触发时间是没有问题的。当安排备份等任务运行时,只要它们在非工作时间运行,就不会有问题。一个系统管理员可以选择一个确定的开始时间,如典型的 cronjob 规范中的 01:05:00,以不与其他任务冲突,但有很大范围的时间值可以达到这个目的。启动时间中的一分钟随机性通常是不相关的。

然而,对于某些任务,精确的触发时间是一个绝对要求。对于这些任务,你可以通过在 timer unit 文件的 Timer 部分添加这样的配置来指定更高的触发时间跨度精度(如精度在一微秒内):

AccuracySec=1us

时间跨度可用于指定所需的精度,以及为重复性或一次性事件定义时间跨度。它可以识别以下单位:

  • usec, us, µs
  • msec, ms
  • seconds, second, sec, s
  • minutes, minute, min, m
  • hours, hour, hr, h
  • days, day, d
  • weeks, week, w
  • months, month, M (定义为 30.44 天)
  • years, year, y (定义为 365.25 天)

/usr/lib/systemd/system中的所有默认 timer 都指定了一个更大的精度范围,因为精确的时间并不关键。看看系统创建的 timer 中的一些规格:

$ grep Accur /usr/lib/systemd/system/*timer
/usr/lib/systemd/system/fstrim.timer:AccuracySec=1h
/usr/lib/systemd/system/logrotate.timer:AccuracySec=1h
/usr/lib/systemd/system/plocate-updatedb.timer:AccuracySec=20min
/usr/lib/systemd/system/snapd.snap-repair.timer:AccuracySec=10min

Timer 类型

优势之一:除了定时场景,还支持基于 event 的触发

systemd timer 具有 cron 所不具备的其他功能,cron 只在特定的、重复的、实时的日期和时间触发。但是,一个 timer 可以被配置为在系统启动后,或在启动后,或在某个定义的服务 unit 激活后的特定时间内触发。这些被称为单调性 timer。单调指的是一个持续增加的计数或序列。这些 timer 不是持久的,因为它们在每次启动后都会重置。

表 1 列出了单调的 timer 以及每个 timer 的简短定义,还有 "OnCalendar" timer,它不是单调的,用于指定未来的时间,可能是重复的,也可能不是。

Timer单调性定义
OnActiveSec=X这定义了一个相对于 timer 被激活的时刻的 timer。
OnBootSec=X这定义了一个相对于机器启动时间的 timer。
OnStartupSec=X这定义了一个相对于服务管理器首次启动时间的计时器。对于系统 timer unit,这与OnBootSec=非常相似,因为系统服务管理器通常在启动时很早就启动。当配置在每个用户服务管理器中运行的单元时,它主要是有用的,因为用户服务管理器一般只在第一次登录时启动,而不是在启动时。
OnUnitActiveSec=X这定义了一个相对于要激活的 timer 最后一次被激活的时间。
OnUnitInactiveSec=X这定义了一个相对于要激活的 timer 最后被停用的时间的定时器。
OnCalendar=这就用日历事件表达式定义了实时 timer。更多关于日历事件表达式的语法信息请参见systemd.time(7)。否则,其语义与OnActiveSec=及相关设置类似。这个 timer 是最像那些与 cron 服务一起使用的 timer。

表 1: systemd timer 定义

单调 timer 的时间跨度可以使用与前面提到的AccuracySec语句相同的快捷名称,但 systemd 将这些名称规范化为秒。例如,你可能想指定一个 timer,在系统启动 5 天后触发一次事件,可以这样写: OnBootSec=5d。如果主机在2020-06-15 09:45:27启动,timer 将在2020-06-20 09:45:27或之后一分钟内触发。

Calendar event 定义

优势之一:相比 cronjob 更灵活的语法

Calendar event 定义是在所需的重复时间触发 timer 的关键部分。首先看一下OnCalendar设置中使用的一些规格。

systemd 及其 timer 使用的时间和日期规格与 crontab 中使用的格式不同。它比 crontab 更灵活,允许以at命令的方式模糊日期和时间。

使用OnCalendar=的 systemdtimer 的基本格式是DOW YYYY-MM-DD HH:MM:SS。DOW(星期)是可选的,其他字段可以使用星号(*)来匹配该位置的任何值。所有日历时间形式都被转换为规范化的形式。如果没有指定时间,则假定其为 00:00:00。如果没有指定日期但指定了时间,那么下一个匹配可能是今天或明天,这取决于当前的时间。名称或数字可用于月份和星期。可以指定每个单位的逗号分隔的列表。单位范围可以在开始和结束值之间用...来指定。

有几个有趣的选项用于指定日期。波浪号(~)可以用来指定该月的最后一天或该月最后一天之前的指定天数。"/"可以用来指定一周中的某一天作为修饰语。

下面是一些在OnCalendar语句中使用的典型时间规格的例子:

Calendar event 定义描述
DOW YYYY-MM-DD HH:MM:SS
*-*-* 00:15:30每年的每个月的每一天,在午夜后的 15 分钟 30 秒。
Weekly每个星期一的 00:00:00
Mon *-*-* 00:00:00与每周相同
Mon与每周相同
Wed 2020-*-*2020 年的每个星期三,00:00:00
Mon..Fri 2021-*-*2021 年的每个工作日的 00:00:00
2023-6,7,8-1,15 01:15:002023 年 6 月、7 月和 8 月的 1 日和 15 日凌晨 01:15:00
Mon *-05~03任何一年的 5 月的下一个星期一,也是月末的第三天。
Mon..Fri *-08~04任何年份的 8 月底前的第 4 天,如果该天也是工作日,则为 8 月底。
*-05~03/2从五月底开始的第三天,两天后再来一次。每年都会重复。请注意,这个表达式使用了(~)。
*-05-03/2五月的第三天,然后在五月的其余时间里每隔一天。每年重复一次。注意,这个表达式使用了破折号(-)。

表 2: 示例OnCalendar event 定义

测试 calendar 定义

优势之一:更丰富的使用/运维命令集

systemd 提供了一个很好的工具来验证和检查 timer 中的日历时间事件规范。systemd-analyze calendar工具解析了一个日历时间事件规范,并提供了规范化的形式以及其他有趣的信息,比如下一个 "elapse"(即匹配)的日期和时间,以及达到触发时间前的大致时间。

首先,看一下未来的一个没有时间的日期:

$ systemd-analyze calendar 2030-06-17Original form: 2030-06-17
Normalized form: 2030-06-17 00:00:00Next elapse: Mon 2030-06-17 00:00:00 CST(in UTC): Sun 2030-06-16 16:00:00 UTCFrom now: 7 years 2 months left

现在添加一个时间。在这个例子中,日期和时间作为非相关实体被单独分析:

$ systemd-analyze calendar 2030-06-17 15:21:16Original form: 2030-06-17
Normalized form: 2030-06-17 00:00:00Next elapse: Mon 2030-06-17 00:00:00 CST(in UTC): Sun 2030-06-16 16:00:00 UTCFrom now: 7 years 2 months leftOriginal form: 15:21:16
Normalized form: *-*-* 15:21:16Next elapse: Wed 2023-04-05 15:21:16 CST(in UTC): Wed 2023-04-05 07:21:16 UTCFrom now: 21h left

要把日期和时间作为一个 unit 来分析,需要用引号把它们括起来。

$ systemd-analyze calendar "2030-06-17 15:21:16"
Normalized form: 2030-06-17 15:21:16Next elapse: Mon 2030-06-17 15:21:16 CST(in UTC): Mon 2030-06-17 07:21:16 UTCFrom now: 7 years 2 months left

现在测试表 2 中的条目。选一个复杂的:

$ systemd-analyze calendar "2023-6,7,8-1,15 01:15:00"Original form: 2023-6,7,8-1,15 01:15:00
Normalized form: 2023-06,07,08-01,15 01:15:00Next elapse: Thu 2023-06-01 01:15:00 CST(in UTC): Wed 2023-05-31 17:15:00 UTCFrom now: 1 month 26 days left

让我们看一个例子,在这个例子中,我们列出了时间戳表达式的下五个执行时间:

$ systemd-analyze calendar --iterations=5 "Mon *-05~3"Original form: Mon *-05~3
Normalized form: Mon *-05~03 00:00:00Next elapse: Mon 2023-05-29 00:00:00 CST(in UTC): Sun 2023-05-28 16:00:00 UTCFrom now: 1 month 23 days leftIter. #2: Mon 2028-05-29 00:00:00 CST(in UTC): Sun 2028-05-28 16:00:00 UTCFrom now: 5 years 1 month leftIter. #3: Mon 2034-05-29 00:00:00 CST(in UTC): Sun 2034-05-28 16:00:00 UTCFrom now: 11 years 1 month leftIter. #4: Mon 2045-05-29 00:00:00 CST(in UTC): Sun 2045-05-28 16:00:00 UTCFrom now: 22 years 1 month leftIter. #5: Mon 2051-05-29 00:00:00 CST(in UTC): Sun 2051-05-28 16:00:00 UTCFrom now: 28 years 1 month left

这应该给你足够的信息来开始测试你的OnCalendar时间规格。

总结

systemd timer 可以用来执行与 cron 工具相同类型的任务,但在触发事件的 calendar 和单调的时间规格方面提供了更多的灵活性。

除此之外,systemd timer 还有的优势包括:

  • 统一日志收集到 systemd 日志
  • 针对时间精确度更详细的配置项
  • 更丰富的使用/运维命令集

快去尝试迁移你的 cronjob 到 systemd timer 吧~😛😛😛

参考资料

  • Use systemd timers instead of cronjobs
  • Fedora 的 systemd 指南
  • Fedora 的 systemd cheat sheet

三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.

相关文章:

为什么我推荐你使用 systemd timer 替代 cronjob?

概述 前几天在使用 Terraform cloud-init 批量初始化我的实验室 Linux 机器。正好发现有一些定时场景需要使用到 cronjob, 进一步了解到 systemd timer 完全可以替换 cronjob, 并且 systemd timer 有一些非常有趣的功能。 回归话题:为什么我推荐你使用 systemd t…...

elasticsearch基础6——head插件安装和web页面查询操作使用、ik分词器

文章目录一、基本了解1.1 插件分类1.2 插件管理命令二、分析插件2.1 es中的分析插件2.1.1 官方核心分析插件2.1.2 社区提供分析插件2.2 API扩展插件三、Head 插件3.1 安装3.2 web页面使用3.2.1 概览页3.2.1.1 unassigned问题解决3.2.2 索引页3.2.3 数据浏览页3.2.4 基本查询页3…...

【Linux】七、进程间通信(二)

目录 三、system V(IPC) 3.1 system V共享内存 3.1.1 共享内存的概念 3.1.2 共享内存的原理 3.1.3 创建共享内存(shmget ) 3.1.4 ftok函数 3.1.5 查看共享内存资源 3.1.6 创建共享内存测试代码 3.1.7 再次理解共享内存 3.1.8 释放共享内存(shm…...

Synchronized学习大总结

目录 1.synchronized特性 2.synchronized如何使用 3.synchronized的锁机制 1.synchronized特性 synchronized 是乐观锁,也是悲观锁,是轻量级锁(j基于自旋锁实现),也是重量级锁(基于挂起等待锁实现),它不是读写锁,是互斥锁,当一个线程抢到锁之后,其它线程阻塞等待,进入synchr…...

VN5620以太网测试——环境搭建篇

文章目录 前言一、新建以太网工程二、Port Configuration三、Link up四 Trace界面五、添加Ethernet Packet Builder六、添加ARP Packet七、添加Ethernet IG总结前言 CANoe(CAN open environment)VN5620 :是一个紧凑而强大的接口,用于以太网网络的分析、仿真、测试和验证。 …...

redis哨兵和集群部署手册

一、哨兵模式原理及作用 1.原理 哨兵(sentinel): 是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现 故障时,通过投票机制选择新的master并将所有slave连接到新的master。所以整个运行哨兵的集…...

ctfshow web入门 java 295 298-300

其他没啥好讲的,都是工具就通杀了 web295 漏洞地址 http://ip/S2-048/integration/saveGangster.action 这里我们可以看到他是解析了 尝试使用网上的payload %{(#dmognl.OgnlContextDEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess#dm):((#container#cont…...

SWIG包装器使用指南——(四)C#使用SWIG简介与实践

SWIG系列:http://t.csdn.cn/cIAcr 文章目录一、简介二、全局函数、变量、常量三、继承四、传递指针、引用、数组与值五、基本类型的指针与引用六、基本类型的数组七、基本类型的默认map规则八、常用的typemap方法九、代码插入十、实践10.1 如何映射Foo*&到ref F…...

HashTable, HashMap 和 ConcurrentHashMap

HashTable, HashMap 和 ConcurrentHashMap 都是 Java 集合框架中的类,用于存储和操作键值对。它们之间存在一些关键区别,如下所示: 1.同步性: HashTable:线程安全,所有的方法都是同步的(synchr…...

ToBeWritten之IoT 技战法

也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬…...

基于ASP.NET开发的医院手术麻醉信息管理系统源码 项目源码

系统主要功能介绍: 门诊科室管理系统:手术快速申请、手术申请、手术审核 麻醉科管理系统:手术安排、术后处方、术后小结、PCS实施及管理记录、手术流程 手术护理系统:手术安排、安排临时手术、添加急诊手术、局麻手术护理、整体护…...

伪加密超具体破解办法,直击原理底层,细致演示!!!

前言: 由于我自己目前在misc和取证工作中,也遇到很多压缩包的问题,我个人非常喜欢做压缩包的题目,但也会遇到伪加密问题难以破解,全网ctf教程我都看完了,但是都觉得不够具体,所以我写一篇博客&…...

ChatGPT大规模封锁亚洲地区账号

我是卢松松,点点上面的头像,欢迎关注我哦! 在毫无征兆的情况下,从3月31日开始OpenAI大规模封号,而且主要集中在亚洲地区,特别是ip地址在台湾、日本、香港三地的,命中率目测40%。新注册的账号、…...

脂肪酸脂质Myristic acid PEG NHS,Myristic-acid PEG NHS ester,肉豆蔻酸PEG活性酯,具有优异疏水性

一、基础产品数据: 中文名:肉豆蔻酸PEG N-羟基琥珀酰亚胺,肉豆蔻酸PEG活性酯 英文名:Myristic acid PEG NHS,Myristic-acid PEG NHS ester,Myristic acid PEG SE 结构式(Structural)…...

MFC - CFormView类学习1

CFormView简介 MFC提供了一个名为CFormView的特殊视图类,我们称其为表单视图。表单视图是指用控件来输入和输出数据的视图,用户可以方便地在表单视图中使用控件。表单视图具有对话框和滚动视图的特性,它使程序看起来象是一个具有滚动条的对话…...

图像预处理方法

图像预处理 膨胀腐蚀概述 ⚫ 膨胀、腐蚀属于形态学的操作, 简单来说就是基于形状的一系列图像处理操作 ⚫ 膨胀腐蚀是基于高亮部分(白色)操作的, 膨胀是対高亮部分进行膨胀, 类似“领域扩张”, 腐蚀是高亮部分被腐蚀, 类似“领域被蚕食” ⚫ 膨胀腐蚀的应用和功能: 消除噪声…...

【蓝桥杯C/C++】专题六:动态规划

专题六:动态规划 目录专题六:动态规划导读什么是动态规划解决的问题解题步骤动态规划应该如何debug记忆化搜索斐波那契数题目代码题解爬楼梯题目代码题解使用最小花费爬楼梯题目代码题解不同路径题目题解dfsdp凑硬币题目题解dfsdp滑雪题目代码题解汉罗塔…...

图的定义和基本术语

图的定义和基本术语1.图的定义2.图的基本术语3.图的分类1.图的定义 图是由顶点和有穷非空集合和顶点边的集合吗,表示为G(V,E)。 G表示一个图,V是图G的顶点(数据元素)的集合,E是图G中顶点之间边的集合。在图中&#xf…...

041:cesium加载Blue Marble地图

第041个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中加载Blue Marble地图。Blue Marble是一个术语,用来描述星球漂浮在浩瀚太空中的形象。早在 1972 年,阿波罗 17 号任务的工作人员就首次捕捉到了地球的标志性卫星图像,并将其称为“Blue Marble”。从那时起,NA…...

【概念梳理】激活函数

一、引言 常用的激活函数如下: 1、Sigmoid函数 2、Tanh函数 3、ReLU函数 4、ELU函数 5、PReLU函数 6、Leaky ReLU函数 7、Maxout函数 8、Mish函数 二、激活函数的定义 多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...