systemd wsl 测试笔记

news2025/1/13 13:27:51

文章目录

    • systemd 简介
    • WSL systemd
    • systemctl
    • journalctl
    • hello service
    • Sleep 与 Timeout 测试
    • Requires 测试
    • After 测试

systemd 简介

在这里插入图片描述

Linux 从关闭到运行, 完整的启动和启动过程有三个主要部分:

  • 硬件启动(Hardware boot): 初始化系统硬件
  • Linux 引导(Linux boot): 加载 Linux 内核,然后加载 systemd
  • Linux 启动(Linux startup): systemd为主机做好生产性工作的准备

systemd 是一个软件套件, 充当系统和服务管理器, 软件平台, 以及作为应用程序和内核之间的粘合剂. 一般作为 PID 1 运行, 是引导期间启动的第一个进程, 也是关机期间终止的最后一个进程. 常见的发行版 Arch Linux, Debian, Ubuntu, Dedora 等都启用了 systemd.

  • System and Service Manager (systemd.io)
  • systemd/systemd: The systemd System and Service Manager (github.com), 目前最新的版本为v252
  • systemd - Wikipedia

流传较广的一个 systemd architecture 的简化示意图 (Learning to love systemd | Opensource.com)

在这里插入图片描述

但 systemd 主要作者的 Peottering 说过 systemd 的开发是 never finished, never complete, but tracking progress of technology, 因此组件或架构也在不断变化着, 如现在的12种Unit类型:

  • .service
  • .socket
  • .device (automatically initiated by systemd)
  • .mount
  • .automount
  • .swap
  • .target
  • .path
  • .timer (which can be used as a cron-like job scheduler)
  • .snapshot
  • .slice (used to group and manage processes and resources)
  • .scope (used to group worker processes, isn’t intended to be configured via unit files)

查看 systemd 版本

$ systemd --version
systemd 245 (245.4-4ubuntu3.18)
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=hybrid

WSL systemd

WSL默认使用 init 作为系统和服务管理器, 使用 pstree 命令查看进程树:

$ pstree
init─┬─init───{init}
     ├─init───init───bash───pstree
     └─{init}

这里 init 是 Linux 内核启动时创建的第一个进程(PID 1)

$ ps ax | grep init
      1 ?        Sl     0:00 /init
      8 ?        Ss     0:00 /init
      9 ?        S      0:00 /init
    100 pts/0    S+     0:00 grep --color=auto init

WSL 从0.76.6 预览版及更高版本开始支持手动开启 systemd, 即把 systemd 作为 PID 1, 让 init 进程成为 systemd 的子进程. 先在 PowerShell 中查看当前WSL的版本

# wsl update
> wsl --version
WSL 版本: 1.0.3.0
内核版本: 5.15.79.1
WSLg 版本: 1.0.47
MSRDC 版本: 1.2.3575
Direct3D 版本: 1.606.4
DXCore 版本: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows版本: 10.0.22623.1037

WSL 版本: 1.0.3.0 支持手动开启 systemd, 编辑WSL系统中的 /etc/wsl.conf 文件添加[boot]选项来启用 systemd:

$ sudo vi /etc/wsl.conf
[boot]
systemd=true

然后就可以 PowerShell 中关掉 WSL

> wsl --shutdown

重新打开 WSL, 会发现启动变慢了一些, 因为现在除了 init 进程, 还要开一堆 systemd 的进程, 启动后, 发现 systemd 已经是 PID 1 了, 而 init 进程成了 systemd 的子进程

$ pstree
systemd─┬─ModemManager───2*[{ModemManager}]
        ├─NetworkManager───2*[{NetworkManager}]
        ├─accounts-daemon───2*[{accounts-daemon}]
        ├─agetty
        ├─anacron───sh───run-parts───mlocate───flock───updatedb.mlocat
        ├─atd
        ├─avahi-daemon───avahi-daemon
        ├─cron
        ├─cups-browsed───2*[{cups-browsed}]
        ├─cupsd───dbus
        ├─dbus-daemon
        ├─gdm3───2*[{gdm3}]
        ├─init─┬─init───{init}
        │      ├─init───init───bash───pstree
        │      ├─login───bash
        │      └─{init}
        ├─2*[kerneloops]
        ├─networkd-dispat
        ├─polkitd───2*[{polkitd}]
        ├─rsyslogd───3*[{rsyslogd}]
        ├─rtkit-daemon───2*[{rtkit-daemon}]
        ├─snapd───21*[{snapd}]
        ├─3*[snapfuse]
        ├─sshd
        ├─switcheroo-cont───2*[{switcheroo-cont}]
        ├─systemd─┬─(sd-pam)
        │         ├─dbus-daemon
        │         └─pulseaudio───2*[{pulseaudio}]
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-network
        ├─systemd-resolve
        ├─systemd-udevd
        ├─udisksd───4*[{udisksd}]
        ├─unattended-upgr───{unattended-upgr}
        ├─whoopsie───2*[{whoopsie}]
        └─wpa_supplicant

但用 ps ax 命令发现 PID 1 是 /sbin/init, 这是什么套娃操作?

$ ps ax
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     0:00 /sbin/init
      2 ?        Sl     0:00 /init
      5 ?        Sl     0:00 plan9 --control-socket 6 --log-level 4 --server-fd 7 --pipe-fd 9 --log-truncate
     51 ?        S<s    0:06 /lib/systemd/systemd-journald
     77 ?        Ss     0:00 /lib/systemd/systemd-udevd

systemctl

systemctl 是 控制systemd系统和服务管理器的主要工具.

常见 Unit 的概念:

  • LOAD = Reflects whether the unit definition was properly loaded. 反映Unit是否正确加载: loaded 或 not-found
  • ACTIVE = The high-level unit activation state, i.e. generalization of SUB. 高级Unit活动状态: active, inactive 或 failed
  • SUB = The low-level unit activation state, values depend on unit type. 低级Unit活动状态, 值取决于Unit类型: running, dead, exited, waiting, mounted, plugged, listening, failed, active等

常用命令

# 列出正在运行的Unit, systemctl list-units 或者直接
systemctl

# 列出所有Unit
systemctl list-units --all
# 列出加载失败的Unit, 类型为12种里面的service
systemctl list-units --failed --type=service
# 列出所有ACTIVE   状态为 inactive 的Unit
systemctl list-units --all --state=inactive

# 启动服务
systemctl start xxx.service
# 停止服务
systemctl stop xxx.service
# 重启服务(热启动)
systemctl restart xxx.service
# 重载服务(冷启动)
systemctl reload xxx.service
# 查看状态
systemctl status xxx

# 使能(创建符号链接, 开机启动)
systemctl enable xxx
# 禁止(删除符号链接)
systemctl disable xxx
# 查看是否使能
systemctl is-enabled xxx

journalctl

systemd 日志配置文件为 /etc/systemd/journald.conf, 可以直接查看或者通过以下命令查看

$ systemd-analyze cat-config systemd/journald.conf

可以通过修改配置文件来设置 是否永久存储日志, 最大的文件大小/数量/时间, 最大的行数, 指定日志级别 等

日志默认的保存目录是 /var/log/journal/(持久性存储persistent) 或 /run/log/journal(易失性存储volatile) , 里面默认存的是二进制日志以节省空间, 除了记录日志本身外, 还会记录大量元数据, 可以用 journalctl 工具查看日志文本, 然后再配合其它命令筛选, 查询或导出

journalctl, Query the journal. 用于查询日志

# 从旧到新打印系统日志 journalctl --system 或者
journalctl
# 从新到旧
journalctl -r

# 打印当前用户的日志, 一般开机自启程序当前用户指的root
journalctl --user

# 查看指定服务的日志
journalctl -u xxx

# 查看指定服务的日志, 不分页
journalctl --no-paper -u xxx

# 持续跟踪指定服务的日志
journalctl -f -u xxx
journalctl -f -u xxx -u yyy

# 查看日志占用磁盘空间
journalctl --disk-usage

# 按照 大小 数量 时间 设置/清理日志 1G 1years
journalctl
     --vacuum-size=BYTES     Reduce disk usage below specified size
     --vacuum-files=INT      Leave only the specified number of journal files
     --vacuum-time=TIME      Remove journal files older than specified time
     
# 验证日志文件的完整性
journalctl --verify

# 查看某个时间段的日志, --since today 或者
journalctl --since "2023-01-05 16:50:00" --until "2023-01-05 16:51:00"

# 查看本次启动后的日志, -b 或 
journalctl --boot
# 查看记录的过往启动的简明信息, 如 -9~0
journalctl -list-boots
# 查看上次启动的日志
journalctl --boot=-1
# 查看最新的10行日志
journalctl --boot --lines=10

# 日志级别
# 0	emerg Emerge系统不可用
# 1	alert Alert必须立即采取行动
# 2 crit Crit紧急情况
# 3	err Err非紧急的错误
# 4	warning Warnning警告
# 5	notice Notice普通但值得注意的事件
# 6	info Info信息
# 7	debug Debug调试

# 指定日志级别查看
journalctl -p err --lines=10
journalctl -p 3 -u xxx.service
# 查看上次启动的err信息
journalctl -b -1 -p err
# 查看上次启动的err信息的最后10行
journalctl -b -1 -p err -n 10

# json 输出
journalctl -b -u xxx.service -o json
journalctl -b -u xxx.service -o json-pretty

# 查看内核日志, 和 dmesg 打印出的类似
journalctl -k

hello service

systemd 常见的两个目录:

  • /etc/systemd/system/, systemd默认从这里读取配置文件, 但用 ls -la 可以看出, 里面的service基本都是符号链接, 指向 /lib/systemd/system, 但直接把配置文件.service 放在这个目录也是可以的
  • /lib/systemd/system, 可以放置真正的配置文件

下面给出一个简单的service示例, 1s打印一次

$ sudo vi /lib/systemd/system/hello.service
[Unit]
Description=Hello World Service
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do echo "Hello World"; sleep 1; done'
Restart=on-failure

[Install]
WantedBy=multi-user.target

可以直接运行

$ sudo systemctl status hello.service

# 因为是后台进程, 默认终端无显示, dmeg里也没有, 可以用status
$ sudo systemctl status hello.service
● hello.service - Hello World Service
     Loaded: loaded (/lib/systemd/system/hello.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2023-01-05 15:12:53 CST; 36s ago
   Main PID: 1508 (bash)
      Tasks: 2 (limit: 38477)
     Memory: 864.0K
     CGroup: /system.slice/hello.service
             ├─1508 /bin/bash -c while true; do echo "Hello World"; sleep 1; done
             └─1560 sleep 1

Jan 05 15:13:20 U20 bash[1508]: Hello World
Jan 05 15:13:21 U20 bash[1508]: Hello World
Jan 05 15:13:22 U20 bash[1508]: Hello World
Jan 05 15:13:23 U20 bash[1508]: Hello World

得益于配置文件里写了 Restart=on-failure, 假设我们不小心杀掉了进程, systemd 会帮我们重新拉起来

# PID号参考上方 Main PID: 1508 (bash)
$ sudo kill -9 1508

# 可以看到进程被重新拉了起来, PID号已经变了
$ sudo systemctl status hello
● hello.service - Hello World Service
     Loaded: loaded (/lib/systemd/system/hello.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2023-01-05 15:18:03 CST; 1s ago
   Main PID: 1854 (bash)
      Tasks: 2 (limit: 38477)
     Memory: 948.0K
     CGroup: /system.slice/hello.service
             ├─1854 /bin/bash -c while true; do echo "Hello World"; sleep 1; done
             └─1856 sleep 1

Jan 05 15:18:03 U20 systemd[1]: Started Hello World Service.
Jan 05 15:18:03 U20 bash[1854]: Hello World
Jan 05 15:18:04 U20 bash[1854]: Hello World

# 持续跟踪服务
$ journalctl -f -u hello

如果系统关掉, 重新打开, 服务并不在运行

$ sudo systemctl status hello.service
● hello.service - Hello World Service
     Loaded: loaded (/lib/systemd/system/hello.service; disabled; vendor preset: enabled)
     Active: inactive (dead)

可以使用 enable 来创建符号链接, 因为配置文件中 WantedBy=multi-user.target, 会创建链接到 /etc/systemd/system/multi-user.target.wants, 而 sudo systemctl status multi-user.target 可以看到是开机启动的, 那么 hello.service 再下次系统启动时会连带着起来.

$ sudo systemctl enable hello.service
Created symlink /etc/systemd/system/multi-user.target.wants/hello.service → /lib/systemd/system/hello.service.

再次重启系统, 就可以看到服务开机启动了

$ sudo systemctl status hello
● hello.service - Hello World Service
     Loaded: loaded (/lib/systemd/system/hello.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2023-01-05 15:29:56 CST; 17s ago
   Main PID: 372 (bash)
      Tasks: 2 (limit: 38477)
     Memory: 768.0K
     CGroup: /system.slice/hello.service
             ├─372 /bin/bash -c while true; do echo "Hello World"; sleep 1; done
             └─949 sleep 1

Jan 05 15:30:04 U20 bash[372]: Hello World
Jan 05 15:30:05 U20 bash[372]: Hello World

小结一下

# 编写配置文件, vi 或者 nano编辑器的 sudo systemctl edit --force --full xxx.service
sudo vi /lib/systemd/system/xxx.service
# 立即运行服务
sudo systemctl start xxx
# 设置开机启动(创建符号链接到 yyy.target.wants 或 yyy.target.requires)
sudo systemctl enable xxx

如果更改了配置文件想要重启服务

# 配置文件修改需要 reload units, 但还不会打断之前服务的运行
sudo systemctl daemon-reload
# 重启服务
sudo systemctl restart xxx

如果想要彻底停止并删掉服务

# 停止当前的运行
sudo systemctl stop xxx
# 禁止开机自启(删掉符号链接)
sudo systemctl disable xxx
# 删掉配置文件
sudo rm -f /lib/systemd/system/xxx.service

Sleep 与 Timeout 测试

服务配置文件中 Restart=on-failure 的默认超时时间是 90s, 也就是 90s 内不返回结果就会认为失败了, 特别是调试的时候, 经常会直接 sleep 一段时间再启动, 如GNSS冷启动超级慢, 有时候 sleep 超过了 90s, sleep 的位置不对会出问题, 下面就演示一下

$ sudo vi /lib/systemd/system/hellox.service
[Unit]
Description=Hello World Service
After=network.target

[Service]
Type=simple
ExecStartPre=/bin/sleep 100				
ExecStart=/bin/bash -c 'while true; do echo "Hellox"; sleep 1; done'	
Restart=on-failure

[Install]
WantedBy=multi-user.target

运行测试发现一直失败, 显示 Failed with result 'timeout'

$ sudo systemctl daemon-reload
$ sudo systemctl restart hellox

$ journalctl -f -u hellox
Jan 05 17:38:04 U20 systemd[1]: hellox.service: start-pre operation timed out. Terminating.
Jan 05 17:38:04 U20 systemd[1]: hellox.service: Control process exited, code=killed, status=15/TERM
Jan 05 17:38:04 U20 systemd[1]: hellox.service: Failed with result 'timeout'.
Jan 05 17:38:04 U20 systemd[1]: Failed to start Hellox Service.
Jan 05 17:38:04 U20 systemd[1]: hellox.service: Scheduled restart job, restart counter is at 1.
Jan 05 17:38:04 U20 systemd[1]: Stopped Hellox Service.
Jan 05 17:38:04 U20 systemd[1]: Starting Hellox Service...

Jan 05 17:39:34 U20 systemd[1]: hellox.service: start-pre operation timed out. Terminating.
Jan 05 17:39:34 U20 systemd[1]: hellox.service: Control process exited, code=killed, status=15/TERM
Jan 05 17:39:34 U20 systemd[1]: hellox.service: Failed with result 'timeout'.
Jan 05 17:39:34 U20 systemd[1]: Failed to start Hellox Service.
Jan 05 17:39:35 U20 systemd[1]: hellox.service: Scheduled restart job, restart counter is at 2.
Jan 05 17:39:35 U20 systemd[1]: Stopped Hellox Service.
Jan 05 17:39:35 U20 systemd[1]: Starting Hellox Service...

如果确实非要 sleep, 有下面几种解决办法

  • 删掉 ExecStartPre=/bin/sleep 100, 把 sleep 100 放到 ExecStart=/bin/bash -c 'sleep 100; while true; do echo "Hellox"; sleep 1; done', 建议用这种方法, restart 服务会立即返回
  • 修改超时时间, 如修改为120s, TimeoutSec=120, 或者不限制 TimeoutSec=0, 这会导致 restart 的时候卡ExecStartPre=/bin/sleep 100 这个100s, 所以不太建议这种方法, 可以使用 --no-block 参数规避
  • sudo systemctl --no-block restart hellox, 让systemctl跳过等待, 也就没有Timeout了, 比较危险, 慎用
  • sleep 往往并不靠谱, 建议不用, 可以试试 After 或者 Requires, 或者修改程序

Requires 测试

本服务启动时, Requires后面的服务也会同时被启动(不会因为sleep迟滞), Requires后的服务失败, 本服务也会终止

修改 hellox.service, 让 hello.service 成为 hellox 的 Requiers

$ sudo vi /lib/systemd/system/hellox.service
[Unit]
Description=Hellox Service
Requires=hello.service

[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do echo "Hellox"; sleep 1; done'
Restart=on-failure

[Install]
WantedBy=multi-user.target

此时 hello.service 没有运行, 启动 hellox, 发现hello也被同时启动了

$ sudo systemctl stop hello hellox
$ sudo systemctl daemon-reload
$ sudo systemctl start hellox
$ journalctl -f -u hello -u hellox
Jan 05 18:59:46 U20 systemd[1]: Started Hello World Service.
Jan 05 18:59:46 U20 systemd[1]: Started Hellox Service.
Jan 05 18:59:46 U20 bash[2535]: Hello World
Jan 05 18:59:46 U20 bash[2536]: Hellox
Jan 05 18:59:47 U20 bash[2535]: Hello World
Jan 05 18:59:47 U20 bash[2536]: Hellox

终止 hello, 发现 hellox 也被牵连终止了. (反过来不会)

$ sudo systemctl stop hello
$ journalctl -f -u hello -u hellox
Jan 05 19:00:53 U20 bash[2558]: Hellox
Jan 05 19:00:53 U20 bash[2557]: Hello World
Jan 05 19:00:53 U20 systemd[1]: Stopping Hello World Service...
Jan 05 19:00:53 U20 systemd[1]: Stopping Hellox Service...
Jan 05 19:00:53 U20 systemd[1]: hello.service: Succeeded.
Jan 05 19:00:53 U20 systemd[1]: Stopped Hello World Service.
Jan 05 19:00:53 U20 systemd[1]: helloy.service: Succeeded.
Jan 05 19:00:53 U20 systemd[1]: Stopped Hellox Service.

After 测试

配置文件中的 After 表示该服务在什么服务启动之后再启动, 其它服务在启动中或者未启动完成则本服务等待, 典型应用如:

  • 许多程序需要联网才能使用, 可以等到网络服务启动后再启动
  • ros应用 依赖 roscore , 可以在roscore服务启动后再启动ros应用
  • 很多日志以时间为log名, 但是嵌入式系统等很多没有后备电池, 需要通过GNSS或者网络NTP, PTP等授时后, 系统时间才会准确, 其它的服务可以等待时间同步的服务完成后再开始运行

修改 hellox.service, 在 hello.service 启动之后再启动, 即 After=hello.service

$ sudo vi /lib/systemd/system/hellox.service
[Unit]
Description=Hellox Service
After=hello.service

[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do echo "Hellox"; sleep 1; done'
Restart=on-failure

[Install]
WantedBy=multi-user.target

现在 hello.service 没有运行, 先启动 hellox:

$ sudo systemctl start hellox

# 发现可以直接运行
$ sudo systemctl status hellox
● hellox.service - Hellox Service
     Loaded: loaded (/lib/systemd/system/hellox.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2023-01-05 15:47:16 CST; 4s ago
   Main PID: 1328 (bash)
      Tasks: 2 (limit: 38477)
     Memory: 796.0K
     CGroup: /system.slice/hellox.service
             ├─1328 /bin/bash -c while true; do echo "Hellox"; sleep 1; done
             └─1333 sleep 1

Jan 05 15:47:16 U20 systemd[1]: Started Hellox Service.
Jan 05 15:47:16 U20 bash[1328]: Hellox
Jan 05 15:47:17 U20 bash[1328]: Hellox

# 停掉hellox
sudo systemctl stop hellox

修改 hello.service, 加上89s的延时

$ sudo vi /lib/systemd/system/hello.service
[Unit]
Description=Hello World Service
After=network.target

[Service]
Type=simple
ExecStartPre=/bin/sleep 89
ExecStart=/bin/bash -c 'while true; do echo "Hello World"; sleep 1; done'
Restart=on-failure

[Install]
WantedBy=multi-user.target

hello.service 先运行起来, 然后趁着89s还没有走完, 运行 hellox.service发现 hellox.service被卡住直到 hello.service 启动完

$ sudo systemctl start hello
# 另一个窗口
$ sudo systemctl start hellox

$ journalctl -f -u hello -u hellox
Jan 05 19:08:30 U20 systemd[1]: Starting Hello World Service...
Jan 05 19:09:59 U20 systemd[1]: Started Hello World Service.	# 89s后hello起来了
Jan 05 19:09:59 U20 bash[2981]: Hello World
Jan 05 19:09:59 U20 systemd[1]: Started Hellox Service.	# hellox 在这里起来了
Jan 05 19:09:59 U20 bash[2983]: Hellox
Jan 05 19:10:00 U20 bash[2981]: Hello World
Jan 05 19:10:00 U20 bash[2983]: Hellox
Jan 05 19:10:01 U20 bash[2981]: Hello World

两个服务都enable, 然后重启系统, 也能看到类似的效果. 按名字顺序, helloy 的PID在hello的后面, 但如果调换两个service的内容(让hello中After=helloy, 让helloy去sleep 89), 就没有After的效果了.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/143162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于ERNIELayoutPDFplumber-UIEX的多方案学术论文信息抽取

本项目链接&#xff1a;https://aistudio.baidu.com/aistudio/projectdetail/5196032?contributionType1 0.问题描述 可以参考issue&#xff1a; ERNIE-Layout在&#xff08;人名和邮箱&#xff09;信息抽取的诸多问题阐述#4031 ERNIE-Layout因为看到功能比较强大就尝试了一…

Linux安装mongodb集群整合SpringBoot

一、Mongodb集群安装 本文介绍基于mongodb的副本机制搭建集群 192.168.139.186CentOS Linux release 7.7.1908 (Core)192.168.139.187CentOS Linux release 7.7.1908 (Core)192.168.139.188CentOS Linux release 7.7.1908 (Core) 准备工作 关闭selinux&#xff0c;关闭防火墙…

近场通信到2027年将达到467.81亿美元

2020年&#xff0c;全球近场通信市场规模为178.75亿美元&#xff0c;预计到2027年将达到467.81亿美元&#xff0c;2021年至2027年的CAGR为14.8%。这是根据Market Statsville Group (MSG)的一份新报告得出的。 近场通信(NFC)是基于无线接口的一系列协议&#xff0c;使得通信设备…

Linux系统的优缺点

相比 Windows 系统&#xff0c;Linux 系统有更好的稳定性&#xff0c;那么除此之外&#xff0c;Linux 系统还有那些优点&#xff08;或者不足&#xff09;呢&#xff1f;一、大量的可用软件及免费软件Linux 系统上有着大量的可用软件&#xff0c;且绝大多数是免费的&#xff0c…

2021年第十二届蓝桥杯软件类省赛python组“回路计算“问题

说明 这一题我不会做&#xff0c;看了官方给出的标准答案之后才明白&#xff0c;我把我学到的思路写下来。 题目 蓝桥学院由21栋教学楼组成&#xff0c;教学楼编号1到21。对于两栋教学楼a和b,当a和b互质时&#xff0c;a和b之间有一条走廊直接相连&#xff0c;两个方向皆可通…

CRM之线索管理的demo搭建方法

1、简介 1.1、案例简介 本文将介绍&#xff0c;如何搭建CRM-线索管理。 1.2、应用场景 CRM-线索管理应用完整记录所有线索资料&#xff0c;合理的对线索进行领取、分配、退回、跟进&#xff0c;实现线索管理智能化。 2、设置方法 2.1、表单搭建 1&#xff09;新建主表【新…

【日常系列】LeetCode《25·贪心2》

数据规模->时间复杂度 <10^4 &#x1f62e;(n^2) <10^7:o(nlogn) <10^8:o(n) 10^8<:o(logn),o(1) 内容 lc 976 &#xff1a;三角形的最大周长 https://leetcode.cn/problems/largest-perimeter-triangle/ 提示&#xff1a; 3 < nums.length < 10^4 1 &l…

Dubbo优雅启动(附源码分析)

Dubbo优雅启动 1. 启动有什么问题 我们知道&#xff0c;应用在运行了一段时间后&#xff0c;执行速度会比刚启动的时候要快。这是因为在 Java 里面&#xff0c;在运行过程中&#xff0c;JVM 虚拟机会把高频的代码编译成机器码&#xff0c;被加载过的类也会被缓存到 JVM 缓存中…

主数据和元数据、数据标准、数据质量有什么关系

企业数据治理涉及的工作很广&#xff0c;包括数据标准、数据质量、数据安全、数据共享机制、元数据管理、主数据管理等。主数据作为企业的黄金数据&#xff0c;对于企业信息化管理具有重要意义。本文将对主数据的概念及主数据与数据治理体系中的几个核心部分的关系和大家做一个…

oracle 查询到的结果在快捷地写入到excel过程中标题部分正确的处理方式

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注回复“书籍”即可获赠Python从入门到进阶共10本电子书今日鸡汤羌笛何须怨杨柳&#xff0c;春风不度玉门关。大家好&#xff0c;我是皮皮。一、前言前几天在Python最强王者交流群【粉丝】问了一个pandas数据处理的问题&…

一篇文章让你掌握HTML(上)

目录 前言 1. 基础认知 1.1 HTML概念 1.2 Web标准 2. HTML骨架结构 3. 开发工具的基本使用 4. 语法规范 4.1 HTML的注释 4.2 HTML标签的结构 4.3 HTML标签的关系 5. 排版标签 5.1 标题标签 5.2 段落标签 5.3 换行标签 5.4 水平线标签 6. 文本格式化标签…

清华教授极力推荐的三本入门学习Python书籍

目录 Python入门书&#xff08;适合初学者&#xff09; Python进阶书&#xff08;适合有基础的&#xff09; Python数据科学&#xff08;适合初学者&#xff09; Python入门书&#xff08;适合初学者&#xff09; 这应该是世界上最畅销的Python编程书&#xff0c;没有之一。…

实战|记一次2022某地HVV中的木马逆向分析

声明&#xff1a;本文仅限于技术讨论与分享&#xff0c;严禁用于非法途径。若读者因此作出任何危害网络安全行为后果自负&#xff0c;与本号及原作者无关。前言事情是这样的&#xff0c;国庆前期某地HVV&#xff0c;所以接到了客户通知他们收到了钓鱼邮件想要溯源直接下载文件逆…

电子模块|光照强度传感器模块 GY-302及其驱动(arduino、STC51、STM32)

电子模块|光照强度传感器模块 GY-302及其驱动&#xff08;arduino、STC51、STM32&#xff09;实物照片模块简介模块特点原理图驱动程序arduinoSTC51STM32实物照片 模块简介 BH1750是一种用于两线式串行总线接口的数字型光强度传感器集成电路。这种集成电路可以根据收集的光线强…

【Linux】文件操作、文件描述符和重定向

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《学会Linux》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;重新谈论文…

【数据结构】5.1 树和二叉树的定义

前言 数形结构的关系是 1 对 n 的&#xff0c;树的每个元素后面都可以有多个后继&#xff0c;但是只能有 1 个前趋。 树形结构&#xff08;非线性结构&#xff09; 结点之间有分支具有层次关系 5.1.1 数的定义 树&#xff08;Tree&#xff09;是 n &#xff08;n > 0&…

java中javaSE与javaEE的区别

javaSE是什么&#xff1f; 怎么说吧&#xff0c;可以理解为javaSE是java的基石&#xff0c;如果将java程序想象成一座高楼大厦&#xff0c;那么javaSE就是地基。 官方的解释&#xff1a; Java SE&#xff08;Java Platform&#xff0c;Standard Edition&#xff09; Java SE 以…

实验室设计基本原则SICOLAB

实验室设计基本原则SICOLAB实验室设计、实验室建设施工SICOLAB实验室布局必须符合实验流程的规律&#xff0c;从样品接收、样品暂存、试剂和耗材储存、前处理和准备、样品分析测试、清洗到废物回收和处理&#xff0c;都必须有一个清晰的流程。要区分人流和物流&#xff0c;以及…

SQL DELETE 语句

DELETE 语句用于删除表中的记录。 SQL DELETE 语句 DELETE 语句用于删除表中的行。 SQL DELETE 语法 DELETE FROM table_name WHERE condition; 参数说明&#xff1a; table_name&#xff1a;要删除的表名称。condition&#xff1a;删除条件&#xff0c;用于指定哪些数据要…

小程序开发经验分享(4)-框架的选择

3个小程序开发框架 小程序开发公认的3个小程序开发框架: 原生、wepy、mpvue。3者个有利弊: 原生框架:微信的亲儿子,可直接在微信开发者工具中开发,方便调试,结构直接对应微信文档,框架无缝升级,最快支持最新版本的开发基础库。缺点是原生开发提供的开发方式比较朴素,…