saltstack企业实战

saltstack官网最新文档

saltstack架构设计

saltstack 高可用方案:Salt官网是有

  • HA
  • Rebalance
    • minion配置里写多个master地址
  • failover(syndic)

架构

  • 操作系统:CentOS7.6
  • salt版本:3000.3
多master

https://www.cnblogs.com/renolei/p/4725455.html
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

minion配置里写多个地址
cat minion | grep -vE "^#|^$"
master:- saltstack.online.net- 2.2.2.2- 3.3.3.3
架构解析
Master01是leader节点, Master02和Master03是follower节点;leader上的配置, state文件, return等文件变动都会完全同步到其他follower节点上;Master01绑定DNS, Minion上的配置是:master:- saltstack.online.net- 2.2.2.2- 3.3.3.3
一台Minion启动是会使用multi-master模块建立每个Master的TCP链接, Zero-MQ通信机制配置Minion自动拉取时, 随机选取Master节点, 达到Rebalance目的;当leader节点Master宕机, 只需要切换DNS, 更新Minion-cnf配置即可, 达到半自动HA目的;一般情况下minion节点配置每天同步一次master配置, 因此完全有主动时间处理master节点宕机问题 -
注意事项

1.2个master并不会共享Minion keys,一个master删除了一个key不会影响另一个
2.不会自动同步File_roots,所以需要手动去维护,如果用git就没问题了
3.不会自动同步Pillar_Roots,所以需要手工去维护,也可以用git
4.Master的配置文件也是独立的

saltstack之syndic的配置

https://www.cnblogs.com/kaishirenshi/p/9420790.html

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

saltstack升级

当升级Salt的时候,master(s)应该首先升级。masters向后兼容,minions运行版本比masters版本新是不能保证运行正常的。只要可能,新masters向后兼容旧minions的特性就会被保留下来。一般来说,唯一例外的情况是有安全漏洞的情况下。

salt的管控方式

salt 命令的使用
Usage: salt [options] ‘’ [arguments]

  1. 调用saltstack提供的模块
  2. 写sls状态文件

组管理

1、官方文档

https://docs.saltstack.com/en/latest/topics/targeting/nodegroups.html

2、分组的方式

https://segmentfault.com/a/1190000000506668

文档 4.4 Compound matchers 和 4.3. Node groups 知道,对目标服务器分组有以下七种方式,这七种方式的标示符分别为:

  1. G – 针对 Grains 做单个匹配,例如:G@os:Ubuntu
  2. E – 针对 minion 针对正则表达式做匹配,例如:E@web\d+.(dev|qa|prod).loc
  3. P – 针对 Grains 做正则表达式匹配,例如:P@os(RedHat|Fedora|CentOS)
  4. L – 针对 minion 做列表匹配,例如:L@minion1.example.com,minion3.domain.com or bl*.domain.com
  5. I – 针对 Pillar 做单个匹配,例如:I@pdata:foobar
  6. S – 针对子网或是 IP 做匹配,例如:S@192.168.1.0/24 or S@192.168.1.100
  7. R – 针对客户端范围做匹配,例如:R@%foo.bar

调用saltstack提供的模块

帮助信息
1 查看用salt的所有模块
salt l-k8s1.ops.bj4.daling.com sys.list_modules2 查看模块提供的操作方法 
salt l-k8s1.ops.bj4 sys.list_functions user3 查看方法的使用
salt l-k8s1.ops.bj4  user.add

写sls状态模块

通过使用state组件提供模块

帮助信息
1 查看用salt的所有模块
salt l-k8s1.ops.bj4 sys.list_state_modules2 查看模块提供的操作方法 
salt l-k8s1.ops.bj4 sys.list_state_functions user3 查看方法的使用
salt l-k8s1.ops.bj4 sys.state_doc user.absent
遵循yaml语法
  1. 同级别代码要有相同缩进:建议4个空格
  2. key: value 冒号后必须要有一个空格
  3. 一个键对应多个值时,每个值单独占一行,每个值需要一个有一个 - 横线
key:- value1- value2- value3
状态文件大体格式 *.sls
任务名称:模块名称:参数参数参数模块名称:参数参数参数
定位保存状态文件

saltstack有环境的概念
状态文件的环境 本质就是一个目录,saltstack默认只识别base环境

定位保存状态文件环境
  • 环境
    • 生产
    • 测试
  • 环境A
  • 环境B
修改master状态文件的相关配置
默认配置
# file_roots:
#   base:
#     - /srv/salt/
#   dev:
#     - /srv/salt/dev/services
#     - /srv/salt/dev/states
#   prod:
#     - /srv/salt/prod/services
#     - /srv/salt/prod/states
#
#file_roots:
#  base:
#    - /srv/salt
修改配置如下(为了测试功能,使用默认base环境)
file_roots:base:- /srv/salt/

创建目录,并重启master

mkdir -p /srv/salt/files
systemctl restart salt-master.service
编写测试sls

写一个创建用户的状态文件 /srv/salt/user.sls

create hadoop user:user.present:- name: hadoop- shell: /sbin/nologin
如何执行状态文件
方式一:state.sls 文件名称

所有的配置不能tab出来

salt l-k8s1.ops.bj4 state.sls user
方式二:state.highstate 执行的就是top.sls里面的操作

不需要指定文件名称,但是必须存在一个入口文件top.sls
定义minion与状态文件间的关系
创建位置为 环境的根目录

cat /srv/salt/top.sls

base: #环境'*':  #目标minion (以命令执行时的主机为准)- user  ##不用加后缀
定义资源的依赖关系
第一个

unless cmd.run模块的参数
只有unless后的命令执行失败,name参数对应的命令才执行

installed dhcp:cmd.run:- name: yum install -y dhcp- unless: rpm -q dhcp
第二个

require 我依赖谁
require_in 我被谁依赖
httpd.sls

install httpd:pkg.installed:- name: httpd
copy config file:file.managed:- source: salt://files/httpd.conf- name: /etc/httpd/conf/httpd.conf- require: - pkg: install httpd
start httpd deamon:service.running:- name: httpd- enable: True- require:- pkg: install httpd- file: copy config file
第三个

使用场景:检测配置文件变化,自动加载配置文件
watch 我关注谁
watch_in 我被谁关注

httpd.sls

copy config file:file.managed:- source: salt://files/httpd.conf- name: /etc/httpd/conf/httpd.confstart httpd deamon:service.running:- name: httpd- enable: True- require:- file: copy config file- watch:- file: copy config file

部署saltstack

https://www.cnblogs.com/xintiao-/p/10380656.html

Salt的master和minion包是分开的。机器只需要安装相应的包即可运行。通常情况下,会有一个master和多个minions。

从updates-testing安装

yum --enablerepo=updates-testing install salt-master
yum --enablerepo=updates-testing install salt-minion
salt master

yum install salt-master salt-minion salt-ssh salt-syndic salt-cloud salt-api -y

rpm --import https://repo.saltstack.com/yum/redhat/7/x86_64/latest/SALTSTACK-GPG-KEY.pub
yum install https://repo.saltstack.com/yum/redhat/salt-repo-latest.el7.noarch.rpm
yum install salt-master
pip install salt
配置

http://docs.saltstack.cn/ref/configuration/master.html

安装后操作 启动
## 方式一 :前台启动 (debug做调试)
salt-master --log-level=debug## 方式二: 后台(daemon)启动salt-master -d## 方式三: 系统脚本启动
systemctl enable salt-master.service
systemctl start salt-master.service
salt minion
安装
yum install https://repo.saltstack.com/yum/redhat/salt-repo-latest.el7.noarch.rpm
yum install salt-minion
pip install salt
配置

http://docs.saltstack.cn/ref/configuration/minion.html

安装后操作
systemctl enable salt-minion.service
systemctl start salt-minion.service

日常操作整理

命令整理

查看帮助

模块
查看模块列表module

salt ‘minion’ sys.list_modules
查看指定module的function用法
salt ‘minion’ sys.list_functions file
查看指定模块的详细用法
salt ‘minion’ sys.doc cmd

模块使用说明

查看配置管理state模块列表
salt ‘minion’ sys.list_state_modules
查看配置管理sate列表指定模块所有方法列表
salt ‘minion’ sys.list_state_functions svn
查看配置管理state列表指定模块详细用法
salt ‘minion’ sys.state_doc file
查看配置管理state列表指定模块的方法分支
salt ‘minion’ sys.state_doc file.managed

pillar变量

查看主机对应的所有pillar变量值
salt ‘’ pillar.data
salt '
’ pillar.items
查看主机对应的多个pillar变量值
salt ‘’ pillar.item roles appname
修改pillar值后需要刷新pillar数据
salt '
’ saltutil.refresh_pillar
查看pillar模块详细用法,其他类似
salt ‘minion’ sys.doc pillar
查看pillar的相关方法
salt ‘minion’ sys.list_functions pillar
“”"
shuke:
- pillar.data
- pillar.ext
- pillar.get
- pillar.item
- pillar.items
- pillar.raw
“”"

grains变量

查看模块用法
salt ‘minion’ sys.list_functions grains
查看item项
salt ‘minion’ grains.ls
查看所有iteams
salt ‘minion’ grains.items
获得某个item值
salt ‘minion’ grains.get os
同步_grains目录下的py脚本至minion
salt ‘minion’ saltutil.sync_all
如果py模块有修改,修改后进行重载
salt ‘minion’ sys.reload_modules

minions在线状态

查看所有minion状态
salt-run manage.status
查看所有minion在线状态
salt-run manage.up
查看所有minion不在线状态
salt-run manage.down

key管理

salt-key 密钥管理,通常在master端执行
salt-key [options]
salt-key -L ##查看所有minion-key
salt-key -a ##接受某个minion-key
salt-key -d ##删除某个minion-key
salt-key -A ##接受所有的minion-key
salt-key -D ##删除所有的minion-key

salt-call相关

salt-call 该命令通常在minion上执行,minion自己执行可执行模块,不是通过master下发job
salt-call [options] [arguments]
salt-call test.ping ##自己执行test.ping命令
salt-call cmd.run ‘ifconfig’ ##自己执行cmd.run函数

文件分发

salt-cp 分发文件到minion上,不支持目录分发,通常在master运行
salt-cp [options] ‘’ SOURCE DEST
salt-cp ‘’ testfile.html /tmp
salt-cp 'test
’ index.html /tmp/a.html
salt ‘S1_0_001_Room’ cp.get_dir salt://package /tmp -v 同步目录
salt ‘S1_0_001_Room’ cp.get_file salt://package/minions.tar.gz /tmp/minions.tar.gz gzip=5 同步文件

其他*

salt-run jobs.active #查看所有minion当前正在运行的jobs
salt ‘’ saltutil.running # 查看正在运行的任务,找到jid
salt '
’ saltutil.kill_job jid # 根据jid杀掉任务
salt ‘*’ saltutil.clear_cache # 清除minion缓存

执行单个命令
salt ‘minion’ cmd.run ‘ps -ef | grep mongod’

测试单个sls模块
salt ‘minion’ state.sls nginx test=True

执行前进行测试
salt ‘minion’ state.highstate test=True

在所有minion上执行状态:
salt ‘minion’ sate.highstate

获取执行jib任务的md5值
salt ‘minion’ hashutil.md5_digest 20170202150211366486

low数据可以使用state.show_lowstate方法查看
salt ‘minion’ state.show_lowstate --out yaml

High State数据可以使用state.show_hoghstate方法查看
salt ‘minion’ state.show_highstate --out yaml

#查看highstate
salt ‘minion’ state.show_highstate
#查看lowdata
salt ‘minion’ state.show_lowstate

#执行所有top.sls
salt ‘*’ state.apply

#执行指定环境下top.sls
salt ‘*’ state.apply saltenv=dev

注:

name:要执行的命令,记住该命令将会在salt-minion的路径和权限下执行
onlyif:用于检查的命令,仅当onlyif选项指向的命令返回true时才执行name定义的命令
unless:用于检查的命令,仅当unless选项指向的命令返回false时才执行name指向的命令

查看wyd用户下进程
salt -N ‘Z1_S2’ cmd.run ‘su -c "ps -u wyd | grep -v top | grep -v bash | grep -v sshd | grep -v grep | grep -v ps | grep -v CMD " wyd’

state中(钩子函数)
requisiterequisite:require/watch/onchanges/onfail/use/prereq/require_in(反转)

==Targeting Minion=

#Glob(默认)
salt ‘*’ test.ping
salt * test.ping

#PCRE 正则表达式
salt -E ‘1in.[e|o|u]n ′ t e s t . p i n g = s a l t − E ′ [ m M ] i n . [ e o u ] n ' test.ping = salt -E '^[mM]in.[eou]n test.ping=saltE[mM]in.[eou]n’ test.ping

#list
salt -L web1,web2,db1 test.ping

#Subnet
salt -S 192.168.1.100 test.ping
salt -S 192.168.0.0/16 test.ping

#Grain
salt -G ‘os:ubuntu’ test.ping
salt -G ‘os_family:Debian’ test.ping
salt -G ‘ip_interfaces:eth0:192.168.1.100’ test.ping
salt -G ‘ipv6:::1’ test.ping
salt --grain-pcre ‘os:red(hat|flag)’ test.ping

#Pillar
salt -I ‘my_var:my_val’ test.ping

#混合(Compound)
salt -C ‘G@os:Ubuntu,I@role:web,S@192.168.1.100/24’ test.ping
salt -C ‘min* or ion’ test.ping
salt -C 'web
or *qa,G@os:Arch’ test.ping

#Nodegroup
salt -N webdev test.ping

添加计划任务
salt ‘S1__Center’ cron.set_job root ‘0’ ‘5’ '’ ‘’ '’ ‘/usr/sbin/logrotate -vf /etc/logrotate.d/acl >/tmp/cutacl_log 2>&1’ identifier=cutacl

删除计划任务
salt -C ‘E@S1_(10001|10002|10003)_’ cron.rm_job wyd 'cd /data/wyd/game_server_1.2.0/log;find . -type f -mtime +15 -name ".log*" -exec rm -rf {} ; 2>&1’ identifier=‘clear log’

相关URL:
http://blog.csdn.net/death_kada/article/details/48547271
http://blog.csdn.net/cnweike/article/details/12746399 pillar

普通用户执行salt (默认root)

普通用户执行salt两种方案:1,salt ACL 2.salt external_auth1.ACL1) 设置master配置文件client_acl:monitor:- test*:- test.*dev:- service.*sa:- .*
2) 重启Masterservice salt-master restart
3) 目录和文件权限chmod +r /etc/salt/master
chmod +x /var/run/salt
chmod +x /var/cache/salt
4) 测试# su - monitor
# salt 'test*' test.ping
# exit; su - sa
# salt '*' test.ping
# salt '*' cmd.run 'uptime'
# exit;
2.external_auth1) 修改master配置文件external_auth:
pam: monitor: – ‘test‘: – test. sa: – .* – 2) 3)与ACL相同4) 测试# salt -a pam 'test*' test.ping    ##会提示输入账号密码,所以external_auth与当前用户无关username: monitorpassword:# su - monitor# salt -a pam '*' cmd.run 'uptime'
username: sa
password:
5) 使用Token不必每次都输入账号密码,使用external_auth每次都是需要密码的,这样多麻烦,这里引入了Token,它会保存一串字符到在当前用户家目录下.salt_token中,在有效时间内使用external_auth是不需要输入密码的,默认时间12hour,可以通过master配置文件修改# salt -T -a pam '*' test.ping
username: sapassword:

target 操作主机匹配

指定你的命令或者模块应用哪写Minion上

globbing 默认

salt ‘test*’ test.ping

RE 正则

salt -E ‘web1-(pro|devel)’ test.ping

List 列表

salt -L ‘127.0.0.1, test*’ test.ping

grains

salt -G ‘os:CentOS’ test.ping

#查看所有grains键/值
salt ‘test*’ grains.items
#查看所有grains项
salt ‘test*’ grains.ls
查看某个grains的值
salt ‘test*’ grains.item num_cpus
在top file中匹配grains

‘node_type:web’:

  • match: grain #没有s
  • webserver
    top file中使用jinja模板

{% set self = grains[‘node_type’] %}
- match: grain

  • {{ self }}
nodegroups 其实就是对Minion分组

首先在master的配置文件中对其分组,推荐写到/etc/salt/master.d/中一个独立的配置文件中,比如nodegroup.conf

vim /etc/salt/master.d/nodegroup.conf
#写到master中也是这个格式,master.d中*.conf是默认动态加载的
nodegroups:
test1: ‘L@test1,test2 or test3*’
test2: ‘G@os:CenOS or test2’

salt -N test1 test.ping #-N指定groupname

在top file中使用nodegroups

‘test1’:

  • match: nodegroup ##意没s
  • webserver
混合指定,就是将以上的混合起来用

G Grains glob G@os:Ubuntu
E PCRE Minion ID E@web\d+.(dev|qa|prod).loc
P Grains PCRE P@os:(RedHat|Fedora|CentOS)
L List of minions L@minion1.example.com,minion3.domain.com or bl*.domain.com
I Pillar glob I@pdata:foobar
S Subnet/IP address S@192.168.1.0/24 or S@192.168.1.100
R Range cluster R@%foo.bar

salt -C ‘G@os:CentOS and L@127.0.0.1,192.168.1.12’ test.ping
top file 指定:

‘webserver* and G:CentOS or L@127.0.0.1,test1’:

  • match: compound
  • webserver
一次在n个minion上执行

-b n
–batch-size n
示例:
salt ‘*’ -b 5 test.ping 5个5个的ping

#salt -a pam ‘*’ test.ping #不会提示输入密码了

salt-minion和salt-master之间如何重新认证

修改了minion端的id之后 比如修改了hostname之后,
在minion端

minion端会将minion的id 存放在/etc/salt/minion_id

文件中,重启不会改变。所以要重新认证就需要以下2步:

1、清空minion_id

/etc/salt/minion_id

2、删除minion存放masterkey的文件pki文件夹下所以的东西
rm -rf /etc/salt/pki/*

3、重启minion
service salt-minion restart

在master端

1、删除pki文件之后,重启即可:
rm -f /etc/salt/pki/master/minions/
2、重启salt-master
service salt-master restart
之后就可以salt-key看到新的minion id了。

salt-api

saltstack提供了一套完整的api,称为salt-api。需要安装部署,完成后可通过编程语言连接api执行日常操作

基于https协议的两个url地址

  • https://x.x.x.x:port/login 调用saltAPI,实现用户认证,返回用户令牌
  • https://x.x.x.x:port 调用saltstack模块

在master端操作:安装配置salt-api

安装salt-api
yum install salt-api pyOpenSSL -y
生成证书及key文件

由于salt-api是基于https的,所有需要相对应的证书和key

生成证书
# 安装完软件自动生成的目录 /etc/pki/tls/certs/cd /etc/pki/tls/certs/make testcert
umask 77 ; \
/usr/bin/openssl genrsa -aes128 2048 > /etc/pki/tls/private/localhost.key
Generating RSA private key, 2048 bit long modulus
...+++
..+++
e is 65537 (0x10001)
Enter pass phrase:
Verifying - Enter pass phrase:
umask 77 ; \
/usr/bin/openssl req -utf8 -new -key /etc/pki/tls/private/localhost.key -x509 -days 365 -out /etc/pki/tls/certs/localhost.crt 
Enter pass phrase for /etc/pki/tls/private/localhost.key:
140243069622160:error:28069065:lib(40):UI_set_result:result too small:ui_lib.c:831:You must type in 4 to 1023 characters
Enter pass phrase for /etc/pki/tls/private/localhost.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:bj
Locality Name (eg, city) [Default City]:bj
Organization Name (eg, company) [Default Company Ltd]:bj
Organizational Unit Name (eg, section) []:bj
Common Name (eg, your name or your server's hostname) []:salt-master
Email Address []:bj@qq.com
基于现有的key,生成一个免密的key:否则直接使用key时,每次启动salt-api时,需要输入密码 (master)
cd /etc/pki/tls/private
openssl rsa -in localhost.key  -out localhost_nopass.key 
ll
修改证书及key的权限
chmod 755  /etc/pki/tls/certs/localhost.crt /etc/pki/tls/private/localhost.key /etc/pki/tls/private/localhost_nopass.key 
创建saltapi用户(密码 master)
useradd -M -s /sbin/nologin saltapi
passwd saltapi
master端:编辑salt-api 配置文件

打开include子配置的注释

default_include: master.d/*.conf

添加认证的配置文件 /etc/salt/master.d/eauth.conf

external_auth:pam: //使用pam实现认证saltapi: //salt-api用户名- .*   //允许saltapi用户调用所有salt模块

添加 saltapi配置文 /etc/salt/master.d/api.conf

rest_cherrypy:port: 8001ssl_crt: /etc/pki/tls/certs/localhost.crtssl_key: /etc/pki/tls/private/localhost_nopass.key
重启master;启动salt-api
systemctl restart salt-master.service
systemctl enable salt-api.service 
systemctl start salt-api.service 
ss -lutnp
通过curl命令测试salt-api可正常工作

实现用户认证,获取用户token

curl -k https://10.13.139.6:8001/login -H "Accept: application/x-yaml" -d username="saltapi" -d password="master" -d eauth="pam"# 返回结果
return:
- eauth: pamexpire: 1592234530.94308perms:- .*start: 1592191330.943079token: 426c3e6d108e724fd2be0c0c54648a34cb446a2cuser: saltapi

基于token测试执行test.ping

curl -k https://10.13.139.6:8001/ -H "Accept: application/x-yaml" -H "X-Auth-Token: 5481c7672e68a1139ede58da7d8372f14c57ab82" -d client='local' -d tgt='*' -d fun='test.ping'# 返回值如下
return:
- l-elkstack1.ops.bj2.test.com: truel-k8s1.ops.bj4.test.com: truel-k8s2.ops.bj4.test.com: truel-k8s3.ops.bj4.test.com: truel-k8s4.ops.bj4.test.com: truel-k8s5.ops.bj4.test.com: truel-k8s6.ops.bj4.test.com: truel-k8s7.ops.bj4.test.com: true
使用python调用salt-api执行命令
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/6/15 11:01 
# @Author : wzsimport requests
import json
try:import cookielib
except:import http.cookiejar as cookielib# 使用urllib2请求https出错,做的设置
import ssl
context = ssl._create_unverified_context()# 使用requests请求https出现警告,做的设置
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
salt_api = "https://10.13.139.6:8001/"class SaltApi:"""定义salt api接口的类初始化获得token"""def __init__(self, url):self.url = urlself.username = "saltapi"self.password = "master"self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36","Content-type": "application/json"# "Content-type": "application/x-yaml"}self.params = {'client': 'local', 'fun': '', 'tgt': ''}self.login_url = salt_api + "login"self.login_params = {'username': self.username, 'password': self.password, 'eauth': 'pam'}#获取tokenself.token = self.get_data(self.login_url, self.login_params).get('token')self.headers['X-Auth-Token'] = self.tokendef get_data(self, url, params):send_data = json.dumps(params)request = requests.post(url, data=send_data, headers=self.headers, verify=False)response = request.json()# print('----->>>>',response)result = dict(response)# print('result集合--->', result['return'][0])return result['return'][0]def salt_command(self, tgt, method, arg=None):"""远程执行命令,相当于salt 'client1' cmd.run 'free -m'"""if arg:# salt内置keyparams = {'client':'local', 'fun': method, 'tgt': tgt, 'arg': arg}else:#salt内置key,定义params参数params = {'client':'local', 'fun': method, 'tgt': tgt}# print ('命令参数: ', params)result = self.get_data(self.url, params)# print ('result--->',result)return resultdef main():print ('==================')print ('同步执行命令')salt = SaltApi(salt_api)# print('token-->',salt.token)salt_client = '*'salt_test = 'test.ping'#salt_test ="grains.items"salt_method = 'cmd.run'salt_params = 'free -m'# 下面只是为了打印结果好看点result1 = salt.salt_command(salt_client, salt_test)for i in result1.keys():print (i, ': ', result1[i])result2 = salt.salt_command(salt_client, salt_method, salt_params)for i in result2.keys():print (i)print (result2[i])printif __name__ == '__main__':main()

  1. m|M ↩︎

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

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

相关文章

【贪心算法】贪心算法一

贪心算法一 1.柠檬水找零2.将数组和减半的最少操作次数3.最大数4.摆动序列 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃😃 1.柠檬水找零 题目…

【2023工业异常检测文献】SimpleNet

SimpleNet:ASimpleNetworkforImageAnomalyDetectionandLocalization 1、Background 图像异常检测和定位主要任务是识别并定位图像中异常区域。 工业异常检测最大的难题在于异常样本少,一般采用无监督方法,在训练过程中只使用正常样本。 解决工业异常检…

无人机黑飞打击技术详解

随着无人机技术的普及,无人机“黑飞”(未经授权或违反规定的飞行)现象日益严重,对公共安全、隐私保护及重要设施安全构成了严重威胁。为有效应对这一挑战,各国政府和安全机构纷纷研发并部署了一系列无人机黑飞打击技术…

光控资本:沪指涨0.59%,酿酒板块大幅拉升,数字货币概念等活跃

19日早盘,两市首要指数全线拉升,深证成指、创业板指涨约1%;场内超4800股飘红。 截至午间收盘,沪指涨0.59%报2733.38点,深证成指涨1.25%,创业板指涨0.99%,两市估计成交4263亿元。 盘面上看&…

C++ 9.19

练习&#xff1a;要求在堆区申请5个double类型的空间&#xff0c;用于存储5名学生的成绩。请自行封装函数完成 1> 空间的申请 2> 学生成绩的录入 3> 学生成绩的输出 4> 学生成绩进行降序排序 5> 释放申请的空间 主程序中用于测试上述函数 #include<ios…

google map小叉号不显示

背景需求 需要在uniapp中接入google地图,研究了一番,都没有找到合适的,现在说一下教程。 效果图 前期工作 这两点缺一不可,否则你啥也看不到。 1、电脑安装L-O-U梯 用于访问G-OO-G-LE的API或者创建google map key。 2、手机安装L-O-U梯 用于显示google地图。我就是手…

项目生命周期的类型

‌项目生命周期的类型包括预测型生命周期、迭代型生命周期、增量型生命周期、适应型生命周期和混合型生命周期。 预测型生命周期&#xff08;或称为瀑布型生命周期&#xff09; 从名称中我们就可以看出&#xff0c;我们对行业和项目是非常了解的&#xff0c;可以预测到下一步…

观后感:《中国数据库前世今生》——时代变迁中的数据库崛起

最近观看了《中国数据库前世今生》纪录片&#xff0c;这部影片详细梳理了从1980年代至今&#xff0c;中国数据库技术发展的跌宕历程。作为一名程序员&#xff0c;这部纪录片让我不禁感慨数据库技术的飞速进步&#xff0c;也让我更深入地理解了数据库技术在我们日常生活中的重要…

计算机毕业设计:Java心理在线测评测试系统开题报告+源代码效果图

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

气膜场馆造价解析:来自气膜厂家的专业解答—轻空间

气膜场馆作为一种新型的建筑形式&#xff0c;凭借其独特的结构和材料优势&#xff0c;逐渐在体育、文旅、工业等领域崭露头角。相较于传统建筑&#xff0c;气膜场馆在造价方面具有显著的优势&#xff0c;尤其是在节能、环保、安全等方面表现突出。然而&#xff0c;气膜场馆的造…

简单题70.爬楼梯 (Java)2024920

问题描述&#xff1a; java&#xff1a; class Solution {public int climbStairs(int n) {int f1 1;int f2 2;if(n<2){return n;}for(int s 3;s < n;s){int t f1 f2;f1 f2;f2 t;}return f2;} }

【C++】C++ STL探索:Priority Queue与仿函数的深入解析

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与Queue 这篇文…

YOLOv9改进策略【注意力机制篇】| MCAttention 多尺度交叉轴注意力

一、本文介绍 本文记录的是基于MCA注意力模块的YOLOv9目标检测改进方法研究。普通的轴向注意力难以实现长距离交互&#xff0c;不利于捕获分割任务中所需的空间结构或形状&#xff0c;而MCA注意力模块通过构建了两个并行轴向注意力之间的交互&#xff0c;更有效地利用多尺度特…

vue3 ant-design 4.x 表格动态行样式设置

vue3 ant-design 4.x 表格动态行样式设置 1. 使用场景2. 实现方式 1. 使用场景 告警数据需要依据是否已读展示不同的文字颜色2. 实现方式 1&#xff09;首先给a-table设置class&#xff0c;然后使用rowClassName属性绑定动态设置样式方法 <a-tableclass"alarm-table…

【沃虎干货】POE网络变压器的原理及应用

POE网络变压器的原理主要是通过改变电压幅度&#xff0c;将来自外部电源的直流电压转化为适合网络设备使用的直流电压。POE&#xff08;Power over Ethernet&#xff09;是一种技术&#xff0c;能够在网络线缆上传输电力&#xff0c;方便部署网络系统&#xff0c;尤其是那些需要…

fmql之驱动程序编写(首次)

看了正点原子的zynq系列的Linux开发指南&#xff08;pdf和视频均有&#xff09;&#xff0c;因此从最简单的程序开始。 驱动程序开发&#xff1a;&#xff08;第四期视频&#xff09; 第3.1讲 我的第一个Linux驱动-字符设备驱动框架_哔哩哔哩_bilibili 学习驱动程序编写之前&am…

手动部署并测试内网穿透(ssh 和 nginx)

原理回顾 首先需要一台连接了公网的云服务器&#xff0c;然后我们要访问的内网穿透对象最好是Linux服务器&#xff0c;比如虚拟机&#xff0c;然后我们通过向云服务器发送指令&#xff0c;云服务器再将指定发送给指定对象&#xff0c;让其能够执行命令。 总结就是&#xff1a…

设置PDF打开密码

为PDF文件设置打开密码是一种有效的保护措施&#xff0c;它能防止未经授权的用户访问文件内容。以下是一份专业指南&#xff0c;详细介绍如何为PDF文件设置打开密码。 打开pdf编辑器&#xff0c;我们点击工具栏中的【文件】功能&#xff0c;选择里面的【属性】 然后在属性设置…

JAVA同城美食探索味蕾新伙伴盛宴拼桌报名系统小程序源码

同城美食探索&#xff0c;味蕾新伙伴盛宴拼桌报名系统等你来&#xff01;&#x1f37d;️&#x1f46d;&#x1f389; &#x1f50d; 开篇&#xff1a;解锁同城美食新地图 &#x1f50d; 在这个快节奏的城市里&#xff0c;你是否厌倦了日复一日的重复餐点&#xff1f;想要探索…

如何恢复已删除/未保存的 Powerpoint 文件

您是否不小心删除了 PPT 文件或由于系统崩溃或病毒攻击而丢失了它&#xff0c;想知道如何恢复它&#xff1f;不要惊慌;您来对地方了。该帖子解释了如何取回已删除或未保存的 PowerPoint 文件。 数据丢失情况很常见&#xff0c;没有人可以预测可能导致数据丢失的原因。但是没有…