L B T

记 录 过 去 的 经 验

环境信息

  • Centos 7
  • containerd.io-1.4.13-3

containerd 相关配置

默认配置文件

containerd 服务默认配置文件为 /etc/containerd/config.toml

/etc/containerd/config.toml
#root = "/var/lib/containerd"
#state = "/run/containerd"
#subreaper = true
#oom_score = 0

Containerd 有两个不同的存储路径,一个用来保存持久化数据,一个用来保存运行时状态。 [1]

/etc/containerd/config.toml
#root = "/var/lib/containerd"
#state = "/run/containerd"
  • root - 用来保存持久化数据,包括 Snapshots, Content, Metadata 以及各种插件的数据。每一个插件都有自己单独的目录,Containerd 本身不存储任何数据,它的所有功能都来自于已加载的插件。
  • state - 用来保存临时数据,包括 socketspid挂载点运行时状态 以及不需要持久化保存的插件数据。
/etc/containerd/config.toml
#oom_score = 0

Containerd 是容器的守护者,一旦发生内存不足的情况,理想的情况应该是先杀死容器,而不是杀死 Containerd。所以需要调整 Containerd 的 OOM 权重,减少其被 OOM Kill 的几率。oom_score 其取值范围为 -10001000,如果将该值设置为 -1000,则进程永远不会被杀死,建议 Containerd 将该值设置为 -9990 之间。如果作为 Kubernetes 的 Worker 节点,可以考虑设置为 -999

containerd 服务配置文件

默认的 containerd 服务的配置为 /usr/lib/systemd/system/containerd.service

/usr/lib/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd

Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5

LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=1048576

TasksMax=infinity
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target

  • Delegate - 这个选项允许 Containerd 以及运行时自己管理自己创建的容器的 cgroups。如果不设置这个选项,systemd 就会将进程移到自己的 cgroups 中,从而导致 Containerd 无法正确获取容器的资源使用情况。

  • KillMode - 这个选项用来处理 Containerd 进程被杀死的方式。默认情况下,systemd 会在进程的 cgroup 中查找并杀死 Containerd 的所有子进程,这肯定不是我们想要的。KillMode 字段可以设置的值如下:

    • control-group -(默认值)当前控制组里面的所有子进程,都会被杀掉
    • process - 只杀主进程。
    • mixed - 主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
    • none - 没有进程会被杀掉,只是执行服务的 stop 命令。

    需要将 KillMode 的值设置为 process,这样可以确保升级或重启 Containerd 时不杀死现有的容器。

客户端工具 ctr 使用

ctr 管理镜像

镜像下载

ctr image pull docker.io/library/nginx:alpine

列出本地镜像

$ ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:455c39afebd4d98ef26dd70284aa86e6810b0485af5f4f222b19b89758cabf1e 9.8 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -

将镜像挂载到本地目录

$ ctr image mount docker.io/library/nginx:alpine /mnt

$ ls /mnt
bin docker-entrypoint.d etc lib mnt proc run srv tmp var
dev docker-entrypoint.sh home media opt root sbin sys usr

卸载已挂载的镜像

ctr image unmount /mnt

ctr 管理 容器

创建容器

ctr container create docker.io/library/nginx:alpine nginx

容器创建后,并没有开始运行,只是分配了容器运行所需的资源及配置的数据结构,这意味着 namespacesrootfs 和容器的配置都已经初始化成功了,只是用户进程(这里是 nginx)还没有启动,容器(进程)状态的变化由 Task 对象实现,通过命令 ctr task 来管理。

启动 ctr container create 创建的容器

ctr task start nginx

以上命令启动之前创建的容器 nginx,未指定其他参数时,容器中的进程在系统前台运行,如需后台运行,可以使用选项 -d

ctr task start nginx -d

也可以直接使用 run 命令,创建并启动容器

ctr run --rm -d docker.io/library/nginx:alpine nginx1

列出容器

ctr container ls

查看容器中进程的状态

$ ctr task ls
TASK PID STATUS
nginx1 5495 RUNNING

查看容器中运行的所有的进程

$ ctr task ps nginx1
PID INFO
5495 -
5531 -
5532 -
5533 -
5534 -

这里的 PID 是宿主机看到的 PID,不是容器中看到的 PID。

查看容器详细信息

ctr container info nginx

删除容器

停止/删除容器中的进程

ctr task delete nginx -f

ctr task pause nginx

以上命令删除/停止容器中的进程,但是并不删除容器,执行以上命令后再执行以下命令,可删除容器

ctr container delete nginx

ctr 没有 stop 容器的功能,只能暂停或者杀死容器。

进入容器

ctr task exec -t --exec-id 1 nginx1 sh

执行 ctr task exec 进入容器,必须制定 --exec-id,值可以随便指定。

namespace 管理

Containerd 相比于 Docker ,多了 Namespace 的概念,使用以下命令,查看所有的 Namespace

$ ctr ns ls
NAME LABELS
default
moby

docker 默认使用 moby 的 Namespace,要使用 ctr 命令查看 docker 创建的容器,需要使用选项 -n moby 指定命名空间,否则 ctr 默认使用 default 命名空间,无法看到 moby 命名空间中的资源

ctr -n moby container ls
CONTAINER IMAGE RUNTIME
17b16c3699cdb88a1ff80d8a7c84724eff393c42186775b58418c90bd178600f - io.containerd.runtime.v1.linux
27fc19226baa91251d63a375a7b1309122334cfb5ceb39aeb67ab1701b708464 - io.containerd.runtime.v1.linux

Kubernetes 默认使用 k8s.io 命名空间

ctr 没有配置或者环境变量可以来配置默认的 Namespace,在 Kubernetes 场景中,可以使用 alias 命令配置 ctr,使其自动指向 k8s.io 的 Namespace

alias ctr='ctr -n k8s.io'

脚注

版本信息

  • Centos 7
  • Kubernetes 1.24
  • Prometheus 2.44.0
  • AlertManager 0.24.0

Prometheus 部署步骤

为 Prometheus 创建专用的 Namespace,此处创建 prometheus

kubectl create namespace prometheus

创建集群角色

Prometheus 使用 Kubernetes API 从 Nodes、Pods、Deployments 等等中读取所有可用的指标。因此,我们需要创建一个包含读取所需 API 组的 RBAC 策略,并将该策略绑定到新建的 prometheus 命名空间。[1]

  1. 创建一个名为 prometheusClusterRole.yaml的文件,并复制以下 RBAC 角色。

    在下面给出的角色中,可以看到,我们已经往 nodes, services endpoints, podsingresses 中添加了 getlist 以及 watch 权限。角色绑定被绑定到监控命名空间。如果有任何要从其他对象中检索指标的用例,则需要将其添加到此集群角色中。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
    name: prometheus
    rules:
    - apiGroups: [""]
    resources:
    - nodes
    - nodes/proxy
    - nodes/metrics
    - services
    - endpoints
    - pods
    verbs: ["get", "list", "watch"]
    - apiGroups:
    - extensions
    resources:
    - ingresses
    verbs: ["get", "list", "watch"]
    - nonResourceURLs: ["/metrics"]
    verbs: ["get"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
    name: prometheus
    roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: prometheus
    subjects:
    - kind: ServiceAccount
    name: default
    namespace: prometheus
  2. 使用下面的命令创建角色
    kubectl apply -f prometheusClusterRole.yaml
阅读全文 »

要将 Python 脚本打包为 Windows 可运行程序,一种常用的方法是使用 PyInstaller。

安装 PyInstaller

pip install pyinstaller

打包

在命令行中,导航到脚本所在的文件夹并运行以下命令

pyinstaller --onefile test_file.py

这会生成一个 dist 目录,里面包含一个名为 test_file.exe 的可执行文件。参数 --onefile 确保所有必要的文件都被包含在单一的可执行文件中。

以上方法打包后的文件点击运行后,桌面会弹窗一个 cmd 窗口,如果关闭了此 cmd 窗口,与其关联的程序也会被关闭。为了阻止这个命令行窗口的出现,并让程序在关闭窗口后仍然运行,你需要在使用 PyInstaller 打包时使用 --noconsole 选项。此外,为了使程序在没有任何可视窗口的情况下静默运行(例如,仅在系统托盘中),你还需要使用 --windowed 选项。

pyinstaller --onefile --noconsole --windowed test_file.py

如果你想要程序在系统托盘中静默运行,并通过系统托盘图标进行交互,那么你需要使用其他库,如 pystray,来创建系统托盘应用。

环境信息

  • centos7 3.10.0
  • kubernetes Server Version: v1.21.2
  • Helm 3.10.0
  • Rancher 2.6

安装

官方安装文档

安装 Helm

安装文档官网参考

helm 安装及使用

安装 Ingress-nginx-controller

安装文档官网参考

ingress-nginx 安装配置

添加 Helm Chart 仓库

添加最新版本,生产环境建议使用稳定版本

helm repo add rancher-latest https://releases.rancher.com/server-charts/latest

为 Rancher 创建命名空间

你需要定义一个 Kubernetes 命名空间,用于安装由 Chart 创建的资源。这个命名空间的名称为 cattle-system

kubectl create namespace cattle-system

安装 cert-manager

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.7.1/cert-manager.crds.yaml

# 添加 Jetstack Helm 仓库
helm repo add jetstack https://charts.jetstack.io

# 更新本地 Helm Chart 仓库缓存
helm repo update

# 安装 cert-manager Helm Chart
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.7.1

安装完 cert-manager 后,你可以通过检查 cert-manager 命名空间中正在运行的 Pod 来验证它是否已正确部署:

$ kubectl get pods -n cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-5b97785fbd-vvscn 1/1 Running 0 77s
cert-manager-cainjector-c8657d84f-6b8qr 1/1 Running 0 77s
cert-manager-webhook-8564679744-hjgkx 1/1 Running 0 77s

通过 Helm 安装 Rancher

helm install rancher rancher-stable/rancher --namespace cattle-system \
--set hostname=rancher.my.com --set bootstrapPassword=admin \
--set ingress.ingressClassName=nginx

安装成功后,输出结果如下

NAME: rancher
LAST DEPLOYED: Wed Oct 12 10:22:25 2022
NAMESPACE: cattle-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Rancher Server has been installed.

NOTE: Rancher may take several minutes to fully initialize. Please standby while Certificates are being issued, Containers are started and the Ingress rule comes up.

Check out our docs at https://rancher.com/docs/

If you provided your own bootstrap password during installation, browse to https://rancher.my.com to get started.

If this is the first time you installed Rancher, get started by running this command and clicking the URL it generates:

```
echo https://rancher.my.com/dashboard/?setup=$(kubectl get secret --namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}')
```

To get just the bootstrap password on its own, run:

```
kubectl get secret --namespace cattle-system bootstrap-secret -o go-template='{{.data.bootstrapPassword|base64decode}}{{ "\n" }}'
```


Happy Containering!

根据提示,浏览器中访问 https://rancher.my.com/dashboard/?setup=admin,正常情况下,显示如下页面

根据页面提示,保持密码,登陆。

阅读全文 »

blackbox_exporter 是一个由 Prometheus 社区维护的项目,它允许用户通过 HTTP、HTTPS、DNS、TCP 和 ICMP 协议对服务进行“黑盒”方式的探测,以检测和监控网络协议的可用性和响应时间。

本文档以在 Kubernetes 中部署 blackbox_exporter 为例,演示其使用方法。

为了能够监控到 Kubernetes 集群内部的部分信息(如 api-server 的证书等),建议 参考文档为其配置 RBAC 策略 以使其能读取 kube-apiserver 相关资源,本文档中的配置示例基于此权限配置。Namespace 为 prometheus

Kubernetes 中部署 blackbox_export

创建 ConfigMap 以外部化 blackbox_export 配置

blackbox_export 基于配置文件运行,将其配置文件通过 Kubernetes 的 ConfiMap 存储,分离运行环境和配置,方便管理。

参考以下配置,创建 ConfigMap

apiVersion: v1
data:
blackbox.yml: |-
modules:
http_2xx:
prober: http
timeout: 10s
http:
preferred_ip_protocol: "ip4" ##如果http监测是使用ipv4 就要写上
tcp_connect:
prober: tcp
kind: ConfigMap
metadata:
name: blackbox-export-config
namespace: prometheus

部署 blackbox_export

参考以下内容,创建 Deployment 和 Service,在此配置中,使用上面创建的 ConfigMap 作为 blackbox_export 的配置文件

apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-blackbox-export
namespace: prometheus
labels:
app: prometheus-blackbox-export
spec:
replicas: 1
selector:
matchLabels:
app: prometheus-blackbox-export
template:
metadata:
labels:
app: prometheus-blackbox-export
spec:
containers:
- name: prometheus-blackbox-export
image: bitnami/blackbox-exporter
args:
- "--config.file=/etc/blackbox/blackbox.yml"
ports:
- containerPort: 9115
resources:
requests:
cpu: 500m
memory: 500M
limits:
cpu: 1
memory: 1Gi
volumeMounts:
- name: blackbox-config-volume
mountPath: /etc/blackbox/
volumes:
- name: blackbox-config-volume
configMap:
defaultMode: 420
name: blackbox-export-config
---
apiVersion: v1
kind: Service
metadata:
name: blackbox-service
namespace: prometheus
spec:
ports:
- name: blackbox-port
port: 9115
protocol: TCP
targetPort: 9115
selector:
app: prometheus-blackbox-export

部署成功后,从 prometheus 的 Namespace 中测试访问 blackbox_export 的 Endpoint blackbox-service:9115,如果是在其他 Namespace,可以使用 Endpoint blackbox-service.prometheus.svc.cluster.local:9115。如果集群的域名不是 cluster.local,修改为实际值。


prometheus-7589d5bbdd-xdjwt:~# curl -v blackbox-service:9115
* Trying 10.111.137.0:9115...
* Connected to blackbox-service (10.111.137.0) port 9115 (#0)
> GET / HTTP/1.1
> Host: blackbox-service:9115
> User-Agent: curl/8.0.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html
< Date: Tue, 26 Sep 2023 09:11:25 GMT
< Content-Length: 544
<
<html>
<head><title>Blackbox Exporter</title></head>
<body>
<h1>Blackbox Exporter</h1>
<p><a href="probe?target=prometheus.io&module=http_2xx">Probe prometheus.io for http_2xx</a></p>
<p><a href="probe?target=prometheus.io&module=http_2xx&debug=true">Debug probe prometheus.io for http_2xx</a></p>
<p><a href="metrics">Metrics</a></p>
<p><a href="config">Configuration</a></p>
<h2>Recent Probes</h2>
<table border='1'><tr><th>Module</th><th>Target</th><th>Result</th><th>Debug</th></table></body>
* Connection #0 to host blackbox-service left intact
</html>

Prometheus 读取 blackbox_exporter 数据

在 Prometheus 配置中添加以下内容,使 Prometheus 抓取 black_exporter 的监控数据

- job_name: 'blackbox_http_2xx'
scrape_interval: 60s
metrics_path: /probe
params:
module: [http_2xx] # Look for a HTTP 200 response.
static_configs:
- targets:
- http://www.google.com:5000/
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-service.prometheus.svc.cluster.local:9115

部署完成后,观察过 Prometheus 的 Target,正常情况下可以看到监控目标的状态。

阅读全文 »

在 SUSE Linux(无论是 openSUSE 还是 SUSE Linux Enterprise Server)中,可以使用 zypper 命令行工具来管理和安装软件包。

更新软件包数据库

在安装任何新的软件包之前,建议首先更新你的软件包数据库,以确保你拥有最新的软件包信息。

sudo zypper refresh

搜索软件包

如果你不确定软件包的确切名称,可以使用 zypper search 来查找它

zypper search <package-name>

安装软件包

sudo zypper install <package-name>

查询软件包信息

要查看关于特定软件包的详细信息,包括描述、版本和依赖关系等,可以使用

zypper info <package-name>

卸载软件包

sudo zypper remove <package-name>

升级系统

要升级所有已安装的软件包到其最新版本,可以使用以下命令

sudo zypper update

常用软件包安装

以下示例安装常用工具包

  • net-tools,提供 netstat 命令
  • iproute2 提供 ipss 等命令
  • iputils 提供 ping 命令
    sudo zypper refresh
    sudo zypper install net-tools
    zypper install iproute2
    sudo zypper install iputils

环境信息

  • Python 3.10
  • huaweicloudsdk 3.1.23

常用方法

华为云 Python SDK 安装方法官网说明

ECS

获取云服务器 (ECS) 实例信息

通过华为云提供的 Python SDK 获取云服务器实例信息 [1]

python
>>> from huaweicloudsdkcore.auth.credentials import BasicCredentials
>>> from huaweicloudsdkecs.v2.region.ecs_region import EcsRegion
>>> from huaweicloudsdkcore.exceptions import exceptions
>>> from huaweicloudsdkecs.v2 import *

>>> ak = 'QONOKCeljdngdsEGSAM'
>>> sk = 'uD4ndlLqP5xDGSrgRRRPJGF8hg^HGkGl2'

>>> credentials = BasicCredentials(ak, sk)

>>> client = EcsClient.new_builder().with_credentials(credentials).with_region(EcsRegion.value_of("cn-east-2")).build()

>>> request = ListServersDetailsRequest()
>>> response = client.list_servers_details(request)


response 返回一个 huaweicloudsdkecs.v2.model.list_servers_details_response.ListServersDetailsResponse 对象,其中包含了服务器数量和服务器详情列表,要转换为 Python 字典对象,可以通过以下方法

python
>>> import json

>>> server_info = json.loads(str(response))

>>> type(server_info)
<class 'dict'>

### 获取查询出的机器数量
>>> server_info['count']
2

### 云服务器列表 list[dict]
>>> server_info['servers']

### 获取云服务器的名称及 id
>>> server_info['servers'][0]['name']
>>> server_info['servers'][0]['id']

### 获取云服务器的配置规格信息
>>> server_info['servers'][0]['flavor']
{'id': 'c3.xlarge.2', 'name': 'c3.xlarge.2', 'disk': '0', 'vcpus': '4', 'ram': '8192'}

### 获取云服务器挂载的磁盘id
>>> server_info['servers'][0]['os-extended-volumes:volumes_attached']
[{'id': '1fd566f2-82bb-49d3-95d1-7452a5868f80', 'delete_on_termination': 'false', 'device': '/dev/vdb'}, {'id': '2deefa5c-e92b-4ec5-9914-10af9919c121', 'delete_on_termination': 'false', 'bootIndex': '0', 'device': '/dev/vda'}]

### 获取云服务器 IP 信息
### 首先在 'metadata' 中获取云服务器的 VPC id 信息,根据 VPC id 获取对应的 ip 信息
>>> server_info['servers'][0]['metadata']
{'lockScene': '', 'charging_mode': '1', 'vpc_id': '6827d6f5-4614-42a5-9762-15d3d173411c', 'metering.product_id': '00301-15033-0--0', 'lockSource': '', 'lockSourceId': '', 'metering.imagetype': 'gold', 'metering.order_id': 'CS23010203413KRGB', 'image_name': 'Windows Server 2016 Standard 64bit', 'metering.resourcespeccode': 'c3.xlarge.2.win', 'os_type': 'Windows', 'metering.resourcetype': '1', 'metering.image_id': 'dd714f2c-f470-43b6-afc8-34d8ec689516', 'os_bit': '64', 'EcmResStatus': '', 'lockCheckEndpoint': '', 'cascaded.instance_extrainfo': 'clock_adjustment:28800,pcibridge:1'}

>>> server_info['servers'][0]['metadata']['vpc_id']
'6827d6f5-4614-42a5-9762-15d3d173411c'

### 其中 {'OS-EXT-IPS:type': 'floating'} 表示公网 IP
>>> server_info['servers'][0]['addresses']['6827d6f5-4614-42a5-9762-15d3d173411c']
[{'version': '4', 'addr': '192.168.0.65', 'OS-EXT-IPS:type': 'fixed', 'OS-EXT-IPS-MAC:mac_addr': 'fa:16:3e:00:76:2a', 'OS-EXT-IPS:port_id': 'c1ec2783-6d3c-4d8a-9c55-abb59c2c648d'}, {'version': '4', 'addr': '159.138.38.203', 'OS-EXT-IPS:type': 'floating', 'OS-EXT-IPS-MAC:mac_addr': 'fa:16:3e:00:76:2a', 'OS-EXT-IPS:port_id': 'c1ec2783-6d3c-4d8a-9c55-abb59c2c648d'}]

根据云服务器 id,查询云服务器挂载的磁盘信息 [2]

python
>>> request = ListServerBlockDevicesRequest(server_id='a7dd4502-cb3e-4754-b7b7-73bcb5696a1c')

>>> response = client.list_server_block_devices(request)

>>> response
{"attachableQuantity": {"free_scsi": 58, "free_blk": 22, "free_disk": 58}, \
"volumeAttachments": [{"bootIndex": 0, "pciAddress": "0000:02:01.0", "volumeId": "2deefa5c-e92b-4ec5-9914-10af9919c121", "device": "/dev/vda", "serverId": "a7dd4502-cb3e-4754-b7b7-73bcb5696a1c", \
"id": "2deefa5c-e92b-4ec5-9914-10af9919c121", "size": 100, "bus": "virtio"}, \
{"pciAddress": "0000:02:02.0", "volumeId": "1fd566f2-82bb-49d3-95d1-7452a5868f80", \
"device": "/dev/vdb", "serverId": "a7dd4502-cb3e-4754-b7b7-73bcb5696a1c", "id": "1fd566f2-82bb-49d3-95d1-7452a5868f80", "size": 100, "bus": "virtio"}]}
阅读全文 »

Akamai CDN API 说明文档,调用 API 之前需要先根据官方文档说明 Create API Client

Python SDK 使用

根据官方文档说明安装 edgegrid-python,并配置 Create API Client Key 信息 [1]

pip install edgegrid-python

Python SDK 使用官方示例

Akamai API 列表

获取账号信息

大多数 API 使用都需要提供 groupIdaccountIdcontractIds,通过以下接口获取这些信息 [2]

python
>>> import requests
>>> from akamai.edgegrid import EdgeGridAuth, EdgeRc
>>> from urllib.parse import urljoin

>>> edgerc = EdgeRc('~/.edgerc')
>>> section = 'default'
>>> baseurl = 'https://%s' % edgerc.get(section, 'host')

>>> s = requests.Session()
>>> s.auth = EdgeGridAuth.from_edgerc(edgerc, section)

>>> result = s.get(urljoin(baseurl, '/papi/v1/groups'))

>>> result.json()
{'accountId': 'act_F-AC-488298736', 'accountName': 'Guangzhou kl Network Technology Co., Ltd', 'groups': {'items': [{'groupName': 'Guangzhou extreme-G-8HGkt-DSA', 'groupId': 'grp_186987767', 'contractIds': ['ctr_G-3JDoujhh']}]}}

如果 Property 中存在分组,每个分组都有一个独立的 groupId

阅读全文 »

环境信息

  • Selenium > 4.0

Selenium 是一个用于自动化 Web 浏览器操作的工具,可以用于模拟用户与网站的交互。

使用 pip 安装 Selenium 库

pip install selenium

Selenium 需要一个 WebDriver 来控制不同的浏览器。可以根据要使用的浏览器下载相应的 WebDriver。以下是一些常见的浏览器和对应的WebDriver下载链接:

下载 WebDriver 并确保它在系统路径中可用。WebDriver 和浏览器具有版本对应关系,要确保版本匹配

selenium 常见用法总结

本示例中以 Chrome 浏览器为例。

  • 创建一个浏览器实例,并请求指定的页面

    from selenium import webdriver
    from selenium.webdriver.common.by import By

    driver = webdriver.Chrome()

    driver.get("https://www.example.com")
  • 关闭当前浏览器窗口

    driver.close()
  • 最大化浏览器窗口

    driver.maximize_window()
  • 后退

    driver.back()
  • 前进

    driver.forward()
  • 刷新页面

    driver.refresh()
  • 关闭浏览器

    driver.quit()

查找元素并进行操作

  • 通过元素 ID 查找元素并输入文本

    element = driver.find_element(By.ID, "element_id")

    element.send_keys("Hello, Selenium!")
  • 通过元素名称查找元素并点击

    element = driver.find_element(by.NAME, "element_name")
    element.click()
  • 通过链接文本查找元素并点击

    element = driver.find_element(By.LINK_TEXT, "Click Here")
    element.click()
  • 根据元素的 class 属性查找元素。如果有多个具有相同 class 属性的元素

    element = driver.find_element(By.CLASS_NAME, "your_class_name")

    element.click()
  • 查找网页源代码。driver.page_source 包含了网页源代码 [1]

    from selenium import webdriver

    driver.implicitly_wait(10)
    driver.get("https://the-internet.herokuapp.com/upload");
    driver.find_element(By.ID,"file-upload").send_keys("selenium-snapshot.jpg")
    driver.find_element(By.ID,"file-submit").submit()
    if(driver.page_source.find("File Uploaded!")):
    print("file upload success")
    else:
    print("file upload not successful")
    driver.quit()

通过 XPath 定位元素

  • 使用绝对 XPath 定位元素(不推荐,因为它对页面结构的变化敏感)
    element = driver.find_element(By.XPATH, "/html/body/div[1]/div/div[3]/p/a")
  • 使用相对XPath定位元素(更具灵活性,建议使用)
    element = driver.find_element_by_xpath("//div[@class='example']/p/a")
    在上面的示例中,我们使用 XPath 定位元素。以下是 XPath 定位的一些常见语法:
    • // :从文档的根节点开始搜索
    • / :从当前节点的子节点中搜索。
    • [] :用于筛选元素,可以包含属性名和值。
    • @ :用于引用元素的属性。

示例:

language_button = driver.find_element(By.XPATH, "//button[contains(@class, 'btn-lang') and contains(@class, 'btn-dropdown')]")

language_button.click()

实际使用中,自己分析 HTML 结构很难找到对的 XPath。这时候需要使用浏览器的开发者工具,在浏览器的开发者工具中,定位到目标元素,可以选择复制 XPath 获得完整的 XPath 路径

如果要获取 XPath 列表中的最后一个元素,可以参考以下方法

(//*[@id="section-event-round"]/div/div[1]/div[3]/div[2]/div[2])[last()]

element = driver.find_element(By.XPATH, "(//*[@id='section-event-round']/div/div[1]/div[3]/div[2]/div[2])[last()]")

这个 XPath 将选择位于 //*[@id="section-event-round"]/div/div[1]/div[3]/div[2]/div[2] 位置的最后一个 <div> 元素。

处理表单

  • 查找表单元素并填写表单字段

    username = driver.find_element(By.ID, "username")
    password = driver.find_element(By.ID, "password")
    username.send_keys("your_username")
    password.send_keys("your_password")
  • 提交表单

    login_button = driver.find_element(By.ID, "login_button")
    login_button.click()

处理下拉框或选择框

  • 通过标签名查找下拉框元素
    from selenium.webdriver.support.ui import Select

    select = Select(driver.find_element(By.TAG_NAME, "select"))

  • 通过文本选择选某一个选择项
    select.select_by_visible_text("Option 1")
  • 通过值选择选某一个选择项
    select.select_by_value("option_value")
  • 过索引选择选某一个选择项
    select.select_by_index(2)

等待元素加载

  • 使用 WebDriverWait 来等待特定元素出现或满足特定条件
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC


    element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "element_id"))
    )

切换窗口

切换窗口要使用窗口句柄来操作

  • 获取当前窗口句柄

    current_window_handle = driver.current_window_handle

  • 获取所有窗口句柄

    all_window_handles = driver.window_handles

  • 切换到新窗口

    driver.switch_to.window(new_window_handle)

截图

  • 截取整个页面的屏幕截图

    driver.save_screenshot("screenshot.png")
  • 截取特定元素的屏幕截图

    element = driver.find_element(By.ID, "element_id")
    element.screenshot("element_screenshot.png")

配置浏览器启动选项

要自定义浏览器的启动选项,可以使用 Options

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options

from selenium.webdriver.chrome.service import Service as ChromeService

# 设置Chrome浏览器的选项
chrome_options = Options()
chrome_options.add_argument("--disable-infobars") # 禁用信息栏
chrome_options.add_argument("--disable-extensions") # 禁用扩展
chrome_options.add_argument("--start-maximized") # 最大化窗口
chrome_options.add_argument("--disable-notifications") # 禁用通知

# 设置字体显示比例为10%
chrome_options.add_argument("--force-device-scale-factor=0.1")

# 页面加载策略.
## normal complete 默认值, 等待所有资源下载
## eager interactive DOM 访问已准备就绪, 但诸如图像的其他资源可能仍在加载
## none Any 完全不会阻塞 WebDriver
chrome_options.page_load_strategy = 'normal'

# 如果 chromedriver 在系统 Path 中,无需指定路径
driver = webdriver.Chrome(service=ChromeService("path/to/chromedriver"), options=chrome_options)

如果要为 Selenium 指定 Chrome 浏览器的路径,使用 binary_location 属性 [2]

from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.binary_location = "D:\Tools\chrome-win64\chrome.exe"

等待元素出现

在使用 Selenium 和浏览器交互的过程中,经常会遇到元素未加载完成而与元素交互导致的失败。这种情况可以使用 time.sleep() 方法等待一段时间。但是这种等待时间无法确定多少合适。 [3]

Implicit waits

Seleniu 也提供了 Implicit waits 机制。这是一个全局配置。默认值为 0。表示元素如果未出现,立即返回错误;如果配置了等待时间, driver 将会等待设置的时间,如果在配置的时间内元素依然未出现,则报错,如果在等待的时间内元素出现,程序立即执行,因此使用 Implicit waits 不会增加额外的等待时间

driver.implicitly_wait(2)
driver.get('https://www.selenium.dev/selenium/web/dynamic.html')
driver.find_element(By.ID, "adder").click()

added = driver.find_element(By.ID, "box0")

Implicit waits 和 Explicit waits 不要混用,否则会使等待时间变长

Explicit waits

Explicit waits 是添加到代码中的循环,用于轮询应用程序以获取特点条件。如果在指定的超时值之前未满足条件,代码将会给出超时错误。

revealed = driver.find_element(By.ID, "revealed")
wait = WebDriverWait(driver, timeout=2)

driver.find_element(By.ID, "reveal").click()
wait.until(lambda d : revealed.is_displayed())

revealed.send_keys("Displayed")

可以使用的条件参考

参考链接

Selenium 文档

脚注

环境信息

  • Centos7 5.4.212-1
  • Docker 20.10.18
  • containerd.io-1.6.8
  • kubectl-1.25.0
  • kubeadm-1.25.0
  • kubelet-1.25.0

安装 ingress-nginx controller

此文档中的配置主要针对基于部署在裸机(安装通用 Linux 发行版的物理机或者云主机系统)上的 Kebernetes 集群

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.1/deploy/static/provider/cloud/deploy.yaml
mv deploy.yaml ingress-nginx-controller-v1.3.1.yaml

基于 hostNetwork 的 ingress-nginx controller

编辑 ingress-nginx-controllerDeployment 配置文件,在 Deployment 中的 .spec.template.spec 下添加字段 hostNetwork: true,以使 ingress-nginx-controller 可以使用节点的主机网络提供对外访问

阅读全文 »

环境信息

  • Centos 7

查看系统启动时间

who

查看最后一次(上次)系统启动的时间

# who -b 
system boot Dec 27 05:06

查看最后一次(上次)系统启动的时间,及运行级别

# who -r 
run-level 5 Dec 27 05:06

last

通过查看 reboot 用户的登陆记录,可以知道系统的启动时间

# last reboot
reboot system boot 3.10.0-1160.76.1 Fri Jan 13 19:20 - 15:59 (236+20:38)
reboot system boot 3.10.0-1160.76.1 Fri Jan 13 19:00 - 15:59 (236+20:58)
reboot system boot 3.10.0-1160.76.1 Tue Dec 20 11:18 - 15:59 (261+04:40)
reboot system boot 3.10.0-1160.76.1 Thu Oct 27 12:04 - 11:17 (53+23:12)
reboot system boot 3.10.0-1160.76.1 Fri Sep 16 16:26 - 11:28 (40+19:02)
reboot system boot 3.10.0-1160.76.1 Mon Aug 22 17:52 - 16:15 (24+22:22)
reboot system boot 3.10.0-1160.76.1 Mon Aug 22 17:15 - 17:51 (00:36)

分割文件

文件太大,需要分割时,可以使用以下命令

split -b 100M -d test.file
选项 说明 示例
-b, --bytes=SIZE 按照指定大小分割文件
-d, --numeric-suffixes 指定分割后的文件后缀为数字
-a, --suffix-length=N 分割后的文件后缀的长度
$ split -b 100M -d test.file
x00 x03 x06 x09 x12 x15 x18 x21 x24 x27 x30 x33
x01 x04 x07 x10 x13 x16 x19 x22 x25 x28 x31 test.file
x02 x05 x08 x11 x14 x17 x20 x23 x26 x29 x32

安装

wget https://nodejs.org/dist/latest/node-v15.12.0-linux-x64.tar.gz
tar -xf node-v15.12.0-linux-x64.tar.gz -C /usr/local
ln -s /usr/local/node-v15.12.0-linux-x64/bin/* /bin/

安装pm2

npm install pm2 -g
npm install -g pm2@3.5.1 # 安装指定版本
npm install -g pm2@latest # 安装最新版本

常见操作

安装包

npm install pm2

安装指定版本的包

npm install -g pm2@3.5.1

查看可用的安装版本

hexo 安装包为例,以下命令查看 hexo 安装包有哪些可选版本

# npm show hexo versions
[
'3.3.9', '3.4.0', '3.4.1', '3.4.2', '3.4.3',
'3.4.4', '3.5.0', '3.6.0', '3.7.0', '3.7.1',
'3.8.0', '3.9.0', '4.0.0', '4.1.0', '4.1.1',
'4.2.0', '4.2.1', '5.0.0', '5.0.1', '5.0.2',
'5.1.0', '5.1.1', '5.2.0', '5.3.0', '5.4.0',
'5.4.1', '5.4.2', '6.0.0', '6.1.0', '6.2.0',
'6.3.0', '7.0.0-rc1', '7.0.0-rc2'
]

查看已安装的包名

以下命令可显示安装的包及它们的版本

npm ls

如果要查看全局类型的包,使用 -g 选项

npm ls -g

卸载安装的包

npm uninstall package_name

卸载全局安装的包

npm uninstall package_name -g

常见错误

WARN EACCES user “root” does not have permission to access the dev dir “/root/.node-gyp/11.15.0”
ERR! stack Error: EACCES: permission denied, mkdir ‘node_modules/sqlite3/.node-gyp’

[解决方法]:

npm install --unsafe-perm

环境信息

  • Centos7

  • Python3

  • wcs-python3-sdk (5.0.35)

网宿云 python sdk 安装命令 pip3 install wcs-python3-sdk, 安装后包含 cli 工具 wcscmd

初始化配置

wcscmd --configure [--config=FILE] 

--config=FILE 配置文件存储路径,默认~/.wcscfg [1]

wcscmd 常用操作

wcscmd listbucket 
wcscmd stat wcs://BUCKET/OBJECT \# 查询文件信息
wcscmd deletePrefix wcs://BUCKET PREFIX \# 根据前缀(文件路径,必须从头开始匹配,不需要最前面的/)删除目录或文件
wcscmd put wcs://BUCKET/file file

列出所有的文件

以下命令列出所有文件列表,并写入文件中

wcscmd listall wcs://BUCKET ./temp/f

python3 sdk 操作

from wcs.commons.config import Config
from wcs.services.client import Client

config_file = "/root/.wcscfg"
cfg = Config(config_file)
cli = Client(cfg)
bucketName = "TestBucket"
buckList = cli.bucket_list(bucketName, marker='') # 列出bucket中的文件列表,每次最多获取1000个,第一页 `marker=''`, 请求第一页的响应中marker的值为新的页的marker,可通过新的marker继续发起请求

脚注

将源站的内容主动预取到 CDN 节点,用户首次访问可直接命中缓存,即提升首次访问速度,又能有效缓解源站压力。

  • 数据格式:请求和响应都支持 json/xml,xml 的参数与 json 的参数基本一致,json 的参数是驼峰分隔,xml 的参数是“-”分隔,详见示例。
  • 限制说明:每个账号的预取并发是 10,调高并发会增加回源的压力,请联系技术支持人员评估。
阅读全文 »

环境信息

  • Centos 7
  • ansible 2.9.27

Playbook 语法示例

ansible playbook 使用的是 YAML 格式的语法。

---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted

playbook 由一个或多个 play 组成。它的内容是一个以 play 为元素的列表。以上示例仅包含一个 play

每一个 play 中包含了一个 tasks 列表,tasks 列表中的每个 task 在其对应的 hosts依次执行即一个 task 执行完毕,下一个 task 才会执行

在运行 playbook 的过程中,如果一个 host 执行 task 失败,这个 host 将从整个 playbook 中移除。如果发生执行失败的情况,需要修正 playbook 中的错误,重新执行。

阅读全文 »

环境信息

  • Centos 7

ssh 免密登陆

在需要免密码登陆的场景下,可以配置 ssh 密钥登陆。配置步骤如下

  1. 在本地服务器上面执行命令生成密钥对
    $ ssh-keygen 
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/testuser/.ssh/id_rsa):
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /home/testuser/.ssh/id_rsa.
    Your public key has been saved in /home/testuser/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:Lzvl8GbOQETBVcTf8lf0Qk9KUQAESs9h8wARud+iQrk testuser@k8s-uat-master1.148962587001
    The key's randomart image is:
    +---[RSA 2048]----+
    | .BBB*=.o+.|
    | oo= =. o o|
    | o.o .+ *.|
    | .. = =|
    | .S. . +.|
    | o...+ . o|
    | . .o*.. .|
    | E o== |
    | ..=o |
    +----[SHA256]-----+
    以上命令生成了公私密钥对,分别存储在了 /home/testuser/.ssh/id_rsa.pub/home/testuser/.ssh/id_rsa 中。
  2. 在本地服务器上面执行命令将其公钥添加到目标主机的 /home/testuser/.ssh/authorized_keys。或者手动拷贝公钥追加到目标主机的 .ssh/authorized_keys
    $ ssh-copy-id -p 30000 testuser@172.31.30.115
    /bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/testuser/.ssh/id_rsa.pub"
    The authenticity of host '[172.31.30.115]:30000 ([172.31.30.115]:30000)' can't be established.
    ECDSA key fingerprint is SHA256:vKD5th2QpWYv/hmt+180BsENDHWNcJdKiEBOH06h/K8.
    ECDSA key fingerprint is MD5:bf:8c:b9:e6:31:92:1f:a9:b6:7b:8f:50:d7:10:9e:fd.
    Are you sure you want to continue connecting (yes/no)? yes
    /bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keystestuser@172.31.30.115's password:

    Number of key(s) added: 1

    Now try logging into the machine, with: "ssh -p '30000' 'testuser@172.31.30.115'"
    and check to make sure that only the key(s) you wanted were added.
  3. 在本地服务器上面验证可以免密登陆到目标服务器。

如果要配置双向免密,将以上步骤反过来操作一遍即可

常见配置

登录服务器,经常遇见以下提示信息,说明有主机一直在尝试暴力破解用户名密码

There were 696 failed login attempts since the last successful login.

查看登录失败的用户名和 ip 地址

$ grep "Failed password for invalid user " /var/log/secure | awk '{print $11,$13}' | sort | uniq -c | sort -k1 -n
3 wangli 47.74.0.77
3 work 47.74.0.77
3 yt 47.74.0.77
3 yx 47.74.0.77
3 yyz 47.74.0.77
3 zabbix 47.74.0.77
3 zd 47.74.0.77
3 zhangfan 47.74.0.77
3 zxy 47.74.0.77
4 client003 47.74.0.77
4 client004 47.74.0.77
4 dell 47.74.0.77
4 ftpuser 47.74.0.77
4 inspur 47.74.0.77
4 wang 47.74.0.77
5 git 47.74.0.77
5 nagios 47.74.0.77
5 testuser 47.74.0.77
6 omnisky 47.74.0.77
7 oracle 47.74.0.77
8 jenkins 47.74.0.77
10 hadoop 47.74.0.77
10 postgres 47.74.0.77
11 ubuntu 47.74.0.77
11 user 47.74.0.77
12 admin 47.74.0.77
15 test 47.74.0.77

阅读全文 »

环境信息

  • Centos 7

sudo 可以配置适当的权限授予普通用户,使普通用户执行 root 用户才能执行的操作

配置 sudo 权限的主要配置文件为 /etc/sudoers/etc/sudoers是一个只读文件,不能直接使用 vim 等编辑器来编辑,要修改此文件,需要以 root 用户身份使用 visudo 命令来修改。

主要配置文件内容如下

/etc/sudoers
## Allow root to run any commands anywhere
root ALL=(ALL) ALL

%wheel ALL=(ALL) NOPASSWD: ALL

各列值含义说明:

  • root 第一列为用户名,如 rootusers%wheel% 开头表示这是一个组,而不是用户
  • ALL=(ALL) 第二列等号左边的 ALL 表示允许从任何主机登录当前的用户账户;等号右边的 ALL 表示第一列的用户可以切换成系统中任何一个其它用户(如:su users);
  • ALL 第三列表示第一列的用户能下达的命令,ALL 表示可以下达任何命令。NOPASSWD: ALL 意味着成员可以执行指定的命令而无需输入密码。

当我们以普通用户身份(以 test 为例)登录,在使用 sudo 命令时报出如下信息:

test is not in the sudoers file. This incident will be reported.

则说明该用户没有在 /etc/sudoers 文件中进行配置,因此无法使用 sudo 命令

AWS 的 Centos 镜像部署后的虚拟机默认使用 centos 用户登陆,登陆后即可执行 sudo su - 切换到 root 用户,此配置由 /etc/sudoers.d/90-cloud-init-users 配置,内容如下:

/etc/sudoers.d/90-cloud-init-users
# cat /etc/sudoers.d/90-cloud-init-users
# Created by cloud-init v. 19.4 on Mon, 31 Oct 2022 07:58:58 +0000

# User rules for centos
centos ALL=(ALL) NOPASSWD:ALL

若要禁止此行为,删除此文件即可。

环境信息

  • Python 3.10
  • Django 4.1

常用配置

创建项目及 app

开始使用 Django 时,需要初始化配置,执行以下命令生成初始化的工程环境 [1]

django-admin startproject mysite

创建 Project 成功后,会生成以 Project 命名的根目录(此处为 mysite),根目录只是你项目的容器, 根目录名称对 Django 没有影响,你可以将它重命名为任何你喜欢的名称。以下为目录结构 [1]

mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py

其中:

  • mysite/mysite/settings.py 为项目配置文件,包括配置 app,数据库等。

创建 App

python manage.py startapp myapp

创建 app 后,会在项目根目录下生成 app 命名的目录。创建 app 后,需要将 app 添加到项目配置文件 settings.py 中的 INSTALLED_APPS

项目配置文件 settings.py 常用配置说明

ALLOWED_HOSTS = ['*']

访问控制,默认只允许从本地访问 Django Server,如果需要远程访问,需要配置远程主机地址,* 可以配置允许任一客户端访问。

配置 mysql 数据库

要为项目配置使用 Mysql 数据库,可以使用以下配置。

settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "vb",
'USER': "root",
"PASSWORD": "dBVgcKGnn0",
'HOST': "127.0.0.1",
"PORT": '3306',
},

}

配置语言为中文

settings.py
LANGUAGE_CODE = 'zh-hans'

配置时区

settings.py
TIME_ZONE = 'Asia/Shanghai'

配置默认的登陆 url 为 Django 后台的登陆 url

如果需要限制只有登陆的用户才能访问 url。可以在视图函数中使用 login_required 装饰器

from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required

# Create your views here.
@login_required
def index(request):
return render(request, 'cloudclient/index.html')

使用了 login_required 装饰器后,未登录的用户会跳转到登陆页面,要配置登陆页面使用 Django Admin 的登陆 url,需要在 settings.py 中添加以下配置

settings.py
LOGIN_URL = 'admin:login'

配置登陆用户自动注销

要配置登陆用户在指定时间内未操作(发送 url 请求)后自动注销,使用以下配置

settings.py
# 设置会话的过期时间为10分钟(以秒为单位)
SESSION_COOKIE_AGE = 600 # 10分钟

# True: 用户的会话在每个请求时都会刷新会话过期时间
SESSION_SAVE_EVERY_REQUEST = True

Django 管理后台配置

  1. 创建 project 后,要使用 Django 管理后台,需要首先初始化数据库并创建 superuser
    python manage.py makemigrations
    python manage.py migrate
    python manage.py createsuperuser
  2. 为 admin 添加路由
    在工程目录中的 urls.py 文件中配置以下内容
    urls.py
    from django.contrib import admin
    from django.urls import path
    from .views import index

    urlpatterns = [
    path('admin/', admin.site.urls),
    path('', index),
    # 项目根 url 既是后台
    # path('', admin.site.urls),
    ]

    如果要在访问项目 / 时,重定向到管理后台,可以在项目的 views.py 文件中添加以下内容,将 / 重定向到 /admin/
    views.py
    from django.shortcuts import redirect

    def index(request):
    return redirect('admin/')

    访问项目 url,此时可以看到登陆后台页面。

脚注

环境信息

  • Python3.10

常用方法

删除 key

scores = {'语文': 89}
scores['数学'] = 93
scores[92] = 5.7

del scores['语文']
del scores['数学']

# 删除指定的 key,并返回 key 对应的值;如果 key 不存在,返回异常:KeyError,可查看 help(dict)
scores.pop(92)

# 删除最后一个 key-value,并以元组的形式返回 (key, value)
scores.popitem()

清空 dict

clear() 用于清空字典中所有的 key-value 对,对一个字典执行 clear() 方法之后,该字典就会变成一个空字典

更新 dict

update() 方法可使用一个字典所包含的 key-value 对来更新己有的字典。在执行 update() 方法时,如果被更新的字典中己包含对应的 key-value 对,那么原 value 会被覆盖;如果被更新的字典中不包含对应的 key-value 对,则该 key-value 对被添加进去;原来的 dict 中存在(更新中不存在)的 key-value 保持不变。

update() 方法也可以用于合并字典,如果 key 重复,会使用新字典中的值替换原来的字典中的值。更新操作不返回任何值,返回结果为 None

dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}

dict1.update(dict2)

print(dict1) # 输出: {'a': 1, 'b': 3, 'c': 4}

合并 dict

要将多个字典的键值合并到一个新的字典中,可以使用字典的解包方式。如果字典中有重复的 key,最终的值为最后的字典中的值

query = {'name': 'd'}
params = {'id': '65220d913a0283df8a'}
merged_dict = {**query, **params}
阅读全文 »

同一个域名使用不同的 HTTPS 重定向规则

在 Cloudflare 中,配置的规则 (比如 自动 HTPTPS 重写 功能) 对所有使用了 Cloudflare 加速的域名都生效。

此时假如有 2 个二级域名 d1.abc.comd2.abc.com,都启用了 Cloudflare 加速功能,此时开启 自动 HTPTPS 重写 功能,则使用 HTTP 协议访问,都会被重定向到 HTTPS。假如域名 d2.abc.com 不想进行 HTTPS 重定向,即使用 HTTP 访问 d2.abc.com 不重定向到 https://d2.abc.com。要实现此功能,参考以下步骤

  1. 首先在 SSL/TLS –> 边缘证书开启 自动 HTPTPS 重写 功能,关闭 始终使用 HTTPS 功能

  2. 自动 HTPTPS 重写 中配置规则,参考下图,定义规则名称,选择 自定义筛选表达式,在表达式中配置筛选条件匹配 d2.abc.com,在下面的设置中 关闭 自动 HTPTPS 重写 功能

通过以上配置即可实现,同一个域名的不同子域名有不同的重定向规则。其他类似需求也可参考此思路配置

阅读全文 »