首页
关于
友链
Search
1
ESXI 一些功能调整
222 阅读
2
天翼云网关3.0/4.0超管密码
182 阅读
3
SoftEther 客户端篇
177 阅读
4
ESXi安装黑群晖
141 阅读
5
SoftEther 服务端篇
127 阅读
默认分类
代码相关
vue
html
python
系统
数据库
docker
安卓
软件分享
杂七杂八的工具
游戏分享
游戏相关
我的家庭影院
登录
Search
标签搜索
python
esxi
git
SoftEther
linux
apscheduler
在线
rclone
Ubuntu
list
列表
idm
激活码
Charles
pdf
免安装
鲁大师
图片查看器
蜂蜜浏览器
honeyview
哥特式
累计撰写
85
篇文章
累计收到
12
条评论
首页
栏目
默认分类
代码相关
vue
html
python
系统
数据库
docker
安卓
软件分享
杂七杂八的工具
游戏分享
游戏相关
我的家庭影院
页面
关于
友链
搜索到
85
篇与
的结果
2024-07-31
acme更新ssl证书
acme实用技巧:稳妥的自动更新证书之宝塔面板_acme证书-CSDN博客acme实用技巧:稳妥的自动更新证书之宝塔面板1. 安装 acme.sh安装很简单, 一个命令:curl https://get.acme.sh | sh -s email=my@example.com把 my@example.com 改成自己的邮箱安装成功后,会为你自动创建定时任务, 如果快过期了, 需要更新, 则会自动更新证书。默认情况下,证书将每60天更新一次。切换默认证书目前 acme.sh 支持 Let’s Encrypt、Buypass、ZeroSSL、SSL.com 和 Google Public CA,默认使用 ZeroSSL,如果需要更换可以使用下面命令:#切换 Let's Encrypt acme.sh --set-default-ca --server letsencrypt #切换 Buypass acme.sh --set-default-ca --server buypass #切换 ZeroSSL acme.sh --set-default-ca --server zerossl #切换 SSL.com acme.sh --set-default-ca --server ssl.com #切换 Google Public CA acme.sh --set-default-ca --server google2. 设置DNS验证文档:https://github.com/acmesh-official/acme.sh/wiki/dnsapi以 CloudFlare为例:使用全局API密钥准备:全局API密钥在 我的个人资料–API令牌–Global API Key 获得设置CloudFlare DNS自动验证使用下面命令:export CF_Key="763eac4f1bcebd8b5c95e9fc50d010b4" #API密钥 export CF_Email="123456@qq.com" #登录邮箱3. 生成证书如果之前安装过证书,后面加 --force 参数,acme.sh --issue --dns dns_cf -d xxx.com -d *.xxx.com成功之后,会在 ~/.acme.sh/目录生成以域名为名称的文件夹,里面包含了证书和各种信息不要通配符,可以去掉:-d *.xxx.com ,如果有多个子域名,后面加 -d x.xxx.com--dns dns_cf 表示使用CloudFlare DNS 自动验证4. 安装证书(重点)假设:你网站使用的是nginx,使用以下命令acme.sh --install-cert -d xxx.com -d *.xxx.com \ --key-file /www/server/panel/vhost/cert/xxx.com/privkey.pem \ --fullchain-file /www/server/panel/vhost/cert/xxx.com/fullchain.pem \ --reloadcmd "service nginx force-reload"使用这条命令时先要生成证书(第三步)不要通配符,可以去掉:-d *.xxx.com ,如果有多个子域名,后面加 -d x.xxx.com命令解读--install-cert #安装证书--key-file #指定安装证书密钥路径--fullchain-file #指定安装证书路径--reloadcmd #重新加载nginx生效为什么要使用那么多参数因为acme证书虽然60天更新一次,但是更新的证书路径是:~/.acme.sh/xxx.com你的域名指向的证书路径并不是在 ~/.acme.sh/不能使用~/.acme.sh/文件夹中的证书文件,它们仅供内部使用,文件夹结构将来可能会更改这些参数会被acme保存起来,下次自动更新时就会自动把证书安装到指定的路径,然后帮你重新加载nginx生效宝塔面板安装证书你要先知道你的域名证书指向的路径在哪,以宝塔面板为例:/www/server/panel/vhost/cert/xxx.com/fullchain.pem /www/server/panel/vhost/cert/xxx.com/privkey.pem可以看到宝塔的证书路径是:/www/server/panel/vhost/cert/如果还没有安装过证书,那么此路径是没有域名证书文件夹的,宝塔面板默认的证书路径格式是:/www/server/panel/vhost/cert/{域名}所以,生成证书后,到~/.acme.sh/目录下找到域名文件夹,复制证书fullchain.cer #证书 xx.com.key #密钥复制到配置ssl证书的地方, 再查看证书路径:最后再执行以下命令,记得修改为你的证书路径acme.sh --install-cert -d xxx.com -d *.xxx.com \ --key-file /www/server/panel/vhost/cert/xxx.com/privkey.pem \ --fullchain-file /www/server/panel/vhost/cert/xxx.com/fullchain.pem \ --reloadcmd "service nginx force-reload"不是复制了证书生效了吗,为什么还要执行上面的命令?因为这些参数会被保存起来,之后的自动更新才有效!5. 签发ECC证书使用以下命令 (以nginx为例)acme.sh --install-cert -d xxx.com -d *.xxx.com --keylength ec-256 \ --key-file /www/server/panel/vhost/cert/xxx.com/privkey.pem \ --fullchain-file /www/server/panel/vhost/cert/xxx.com/fullchain.pem \ --reloadcmd "service nginx force-reload"多了 --keylength ec-256 参数6.强制更新证书所有证书将每60天自动更新一次,但你要强制更新的话acme.sh --renew -d xxx.com --force或者,对于ECC证书:acme.sh --renew -d xxx.com --force --ecc如何停止证书续订要停止证书的续订,您可以执行以下操作以从续订列表中删除证书:acme.sh --remove -d xxx.com [--ecc]不会从磁盘中删除证书/密钥文件。您可以自己删除相应的目录 (例如 ~/.acme.sh/xxx.com )。如何升级 acme.sh您可以将acme.sh更新为最新代码:acme.sh --upgrade您还可以启用自动升级:acme.sh --upgrade --auto-upgrade然后acme.sh将自动保持最新。禁用自动升级:acme.sh --upgrade --auto-upgrade 0
2024年07月31日
26 阅读
1 评论
1 点赞
2024-07-03
实现 MySQL8 查询 JSON 字段
步骤 1: 创建表首先,我们需要创建一个包含 JSON 数据类型字段的表。假设我们要创建一个名为 users 的表,其中包含一个名为 info 的 JSON 字段。CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, info JSON );以上代码创建了一个名为 users 的表,其中包含 id 和 info 两个字段。id 字段是主键,info 字段是 JSON 类型。步骤 2: 插入数据接下来,我们需要向表中插入一些包含 JSON 数据的示例数据。INSERT INTO users (info) VALUES ('{"name": "John", "age": 30, "city": "New York"}'), ('{"name": "Alice", "age": 25, "city": "London"}'), ('{"name": "Bob", "age": 35, "city": "Paris"}');以上代码向 users 表中插入了三条数据,每条数据都包含一个 JSON 对象。步骤 3: 查询 JSON 字段现在,我们可以开始查询包含 JSON 字段的数据了。以下是一些常用的查询操作。查询 JSON 字段的所有数据要查询 JSON 字段的所有数据,可以使用简单的 SELECT 语句。SELECT * FROM users;以上代码将返回 users 表中所有数据。查询 JSON 字段的特定属性要查询 JSON 字段的特定属性,可以使用 -> 或 ->> 运算符。SELECT info->'$.name' AS name, info->'$.age' AS age FROM users;以上代码将返回 users 表中每行数据的 name 和 age 属性。查询 JSON 字段的条件要查询满足特定条件的 JSON 字段数据,可以使用 WHERE 子句。SELECT * FROM users WHERE info->'$.age' > 30;以上代码将返回 users 表中 age 大于 30 的数据。查询 JSON 数组中的值如果 JSON 字段是一个数组,可以使用 ->> 运算符和 JSON_TABLE 函数来查询数组中的值。SELECT jt.value FROM users, JSON_TABLE(info, '$.hobbies[*]' COLUMNS (value VARCHAR(255) PATH '$')) AS jt;
2024年07月03日
15 阅读
0 评论
0 点赞
2024-07-02
小米14 pro设置
1. 关闭5G网络进入拨号界面,输入*#*#54638#*#*回到设置-->移动网络-->5G网络点进去关闭就好
2024年07月02日
41 阅读
0 评论
0 点赞
2024-07-02
【Django】执行查询——查询JSONField
JSONField本篇的例子以下面这个模型为基础:from django.db import models class Dog(models.Model): name = models.CharField(max_length=200) data = models.JSONField(null=True) def __str__(self): return self.name 保存和查询None值在使用JSONField时,要注意空值的处理,注意区分SQL NULL和JSON null保存None值我们首先创建两个Dog实例from django.db.models import Value, JSONField Dog.objects.create(name="Max", data=None) # SQL NULL. # <Dog: Max> Dog.objects.create(name="Archie", data=Value(None, JSONField())) # JSON null. # <Dog: Archie>观察两个实例在数据库中的表现,可以发现SQL NULL和JSON null是不一样的。查询None值查询时,None值将被解释为JSON null,要查询SQL NULL,需要使用isnull:Dog.objects.filter(data=None) # <QuerySet [<Dog: Archie>]> Dog.objects.filter(data=Value(None, JSONField())) # <QuerySet [<Dog: Archie>]> Dog.objects.filter(data__isnull=True) # <QuerySet [<Dog: Max>]> Dog.objects.filter(data__isnull=False) # <QuerySet [<Dog: Archie>]> 对比可以发现,data=None在保存时存储为SQL NULL,查询时解释为JSON null根据键值查找根据json数据的键进行查找,用__连接,可以多个键连接一起,如果某个值是一个列表,要进行索引,就用整数代表该列表的索引。例子:Dog.objects.create( ... name="Rufus", ... data={ ... "breed": "labrador", ... "owner": { ... "name": "Bob", ... "other_pets": [ ... { ... "name": "Fishy", ... } ... ], ... }, ... }, ... ) # <Dog: Rufus> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": None}) # <Dog: Meg> # __连接键进行查找 Dog.objects.filter(data__breed="collie") # <QuerySet [<Dog: Meg>]> # 多个键连接进行查找 Dog.objects.filter(data__owner__name="Bob") # <QuerySet [<Dog: Rufus>]> # 某个值是一个列表,要进行索引,就用整数代表该列表的索引 Dog.objects.filter(data__owner__other_pets__0__name="Fishy") # <QuerySet [<Dog: Rufus>]> # 查询缺少的键,使用isnull查找 Dog.objects.create(name="Shep", data={"breed": "collie"}) # <Dog: Shep> Dog.objects.filter(data__owner__isnull=True) # <QuerySet [<Dog: Shep>]> 包含与键查找containscontains 查询返回的对象是那些包含给定键值对的顶层字段的对象。Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"}) # <Dog: Rufus> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"}) # <Dog: Meg> Dog.objects.create(name="Fred", data={}) # <Dog: Fred> Dog.objects.filter(data__contains={"owner": "Bob"}) # <QuerySet [<Dog: Rufus>, <Dog: Meg>]> Dog.objects.filter(data__contains={"breed": "collie"}) # <QuerySet [<Dog: Meg>]> contained_by这个可以理解为 contains 查询的反向。 要查询的对象满足这样的条件:其该字段对应的数据是传递的值的子集。Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"}) # <Dog: Rufus> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"}) # <Dog: Meg> Dog.objects.create(name="Fred", data={}) # <Dog: Fred> Dog.objects.filter(data__contained_by={"breed": "collie", "owner": "Bob"}) # <QuerySet [<Dog: Meg>, <Dog: Fred>]> Dog.objects.filter(data__contained_by={"breed": "collie"}) # <QuerySet [<Dog: Fred>]> has_key返回数据顶层的键中有给定值的对象。Dog.objects.create(name="Rufus", data={"breed": "labrador"}) # <Dog: Rufus> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"}) # <Dog: Meg> Dog.objects.filter(data__has_key="owner") # <QuerySet [<Dog: Meg>]> has_keys返回数据顶层的键都包含在给定列表中的对象。Dog.objects.create(name="Rufus", data={"breed": "labrador"}) # <Dog: Rufus> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"}) # <Dog: Meg> Dog.objects.filter(data__has_keys=["breed", "owner"]) # <QuerySet [<Dog: Meg>]> has_any_keys返回数据顶层的键中有至少1个在给定列表中的对象,比has_keys条件更宽松。Dog.objects.create(name="Rufus", data={"breed": "labrador"}) # <Dog: Rufus> Dog.objects.create(name="Meg", data={"owner": "Bob"}) # <Dog: Meg> Dog.objects.filter(data__has_any_keys=["owner", "breed"]) # <QuerySet [<Dog: Rufus>, <Dog: Meg>]>
2024年07月02日
18 阅读
0 评论
0 点赞
2024-06-28
python关键字
在Python中,assert是一个关键字,用于编写断言(assertion)。断言是一种用于检查程序中的条件是否为真的方法,通常用于调试和测试目的。当使用assert时,程序会在断言条件为假的情况下引发AssertionError异常。assert的语法如下:assert condition, message其中,condition是要检查的条件,如果条件为假,将会引发AssertionError异常。message是可选的,用于在断言失败时指定错误消息。以下是一个简单的示例:def divide(x, y): assert y != 0, "除数不能为零" return x / y result = divide(6, 3) # 不会触发断言异常 print(result) result = divide(6, 0) # 会触发断言异常,抛出AssertionError: 除数不能为零在上面的示例中,assert y != 0, "除数不能为零"用于检查除数是否为零,如果为零则触发AssertionError异常,并且指定了错误消息"除数不能为零"。这有助于在程序中快速识别和调试问题,并提供有用的错误信息。需要注意的是,一般情况下,assert语句在生产环境中通常会被禁用,因为它们可能会暴露敏感信息或导致安全问题。然而,在开发和测试阶段,assert语句是一个非常有用的工具,可以帮助程序员快速发现和修复问题。
2024年06月28日
14 阅读
0 评论
0 点赞
2024-05-31
Django查询技巧
查询每个供货商的商品库存如果supplier_supplier.id是每个供应商的ID,并且在extra()方法中使用原始SQL查询来计算每个供应商的库存总和,可以按如下方式操作:from django.db.models import Sum # 假设您有名为Supplier的模型,它有一个名为supplier的外键字段指向supplier_supplier模型 # 获取每个供应商的库存总和 supplier_stock_sums = Supplier.objects.extra( select={'stock_sum': 'SELECT IFNULL(SUM(main_product.stock), 0) FROM main_product WHERE main_product.supplier_id = supplier_supplier.id AND main_product.status = 10'} ) # 打印每个供应商的库存总和 for supplier in supplier_stock_sums: print(f"供应商 {supplier.id} 的库存总和为 {supplier.stock_sum}")在上面的示例中,在extra()方法的select参数中使用了原始SQL查询,并在查询中引用了supplier_supplier.id来表示每个供应商的ID。这样就可以计算每个供应商的库存总和。
2024年05月31日
14 阅读
0 评论
0 点赞
2024-05-26
可道云配置
修改的东西app/function/web.function.php// 增加最后的判断: || $_SERVER['HTTP_CF_VISITOR'] function http_type(){ if( (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') || $_SERVER['SERVER_PORT'] === 443 || $_SERVER['HTTP_CF_VISITOR'] ){ return 'https'; } return 'http'; } function get_host() { $httpType = http_type(); // 增加这里 $port = $_SERVER['SERVER_PORT']=='80' ? '' : ':'.$_SERVER['SERVER_PORT']; $host = $_SERVER['SERVER_NAME'].$port; $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'].$port : $host; // 修改的内容结束 if(isset($_SERVER['HTTP_X_FORWARDED_HOST'])){//proxy $hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']); $host = trim($hosts[0]); }else if(isset($_SERVER['HTTP_X_FORWARDED_SERVER'])){ $host = $_SERVER['HTTP_X_FORWARDED_SERVER']; } // 如果域名相同 则根据referer自适应https; if(isset($_SERVER['HTTP_REFERER'])){ $urlInfo = parse_url($_SERVER['HTTP_REFERER']); if($urlInfo['host'] == trim($host,'/')){ if($httpType == 'http' && $urlInfo['scheme'] == 'https'){$httpType = 'https';} } } return $httpType.'://'.trim($host,'/').'/'; }最新的安装包反代的时候有问题,下载以前的https://static.kodcloud.com/update/download/kodbox.1.40.zip
2024年05月26日
18 阅读
0 评论
0 点赞
2024-05-26
Minio集群配置
docker-compose搭建多主机分布式miniominio介绍Minio 是个基于 Golang 编写的开源对象存储套件,虽然轻量,却拥有着不错的性能。官网地址:MinIO | High Performance, Kubernetes Native Object Storage何为对象存储?我们来看下阿里云 OSS (Object Storage Service)的介绍:对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。对于中小型企业,如果不选择存储上云,那么 Minio 是个不错的选择,麻雀虽小,五脏俱全。当然 Minio 除了直接作为对象存储使用,还可以作为云上对象存储服务的网关层,无缝对接到 Amazon S3、MicroSoft Azure。1.配置时间同步、关闭防火墙和selinux2.确保主机都安装了docker 以及docker compose<br/> docker-compose.yml # Settings and configurations that are common for all containers # minio节点之间默认使用9000来连通,所以容器把9000暴露出来,9001是console端口,每个节点设置两块磁盘 x-minio-common: &minio-common image: minio/minio:latest command: server --console-address ":9001" http://minio{1...2}/data{1...2} expose: - "9000" - "9001" # 增加host映射,以便两个节点之间通过域名连通 extra_hosts: minio1: 192.168.188.40 minio2: 192.168.188.41 environment: MINIO_ROOT_USER: 用户名 MINIO_ROOT_PASSWORD: 密码 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 5 # starts 3 docker containers running minio server instances. # using nginx reverse proxy, load balancing, you can access # it through port 9000. # 数据盘挂载目录,按需修改 services: minio1: <<: *minio-common container_name: minio1 hostname: minio1 volumes: - ./data1-1:/data1 - ./data1-2:/data2 ports: - "9000:9000" - "9001:9001" minio2: <<: *minio-common container_name: minio2 hostname: minio2 volumes: - ./data2-1:/data1 - ./data2-2:/data2 ports: - "9000:9000" - "9001:9001"3.将以上文件放在每台机器的同一目录下,去分别启动# 拉镜像 ./docker compose pull # 后台启动容器,三台机器分别对应各自节点 mini01 /minio2 (切勿单台启动多个) # 在188-40上执行 ./docker compose up -d minio1 # 在188-41上执行 ./docker compose up -d minio2 4. 配置负载均衡服务器上安装nginx创建网站修改配置文件,上面增加upstream console { ip_hash; server 192.168.188.40:9001 weight=100; server 192.168.188.41:9001 weight=10; }weight=number:用来设置服务器的权重,默认为1,权重数字越大,被分配到请求的几率越大。该权重值主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的,所以此策略比较适合服务器的硬件配置差别比较大的情况。nginx 的 upstream目前支持 4 种方式的分配1)、轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。2)、weight 指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。3)、ip_hash 每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。4)、fair(第三方) 按后端服务器的响应时间来分配请求,响应时间短的优先分配。5)、url_hash(第三方)反向代理的配置:配置文件#PROXY-START/ location ^~ / { proxy_pass http://console; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; # proxy_hide_header Upgrade; add_header X-Cache $upstream_cache_status; #Set Nginx Cache set $static_fileZhvl5TVI 0; if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" ) { set $static_fileZhvl5TVI 1; expires 1m; } if ( $static_fileZhvl5TVI = 0 ) { add_header Cache-Control no-cache; } # 缩略图配置 set $width -; set $height -; if ($arg_w != '') { set $width $arg_w; } if ($arg_h != '') { set $height $arg_h; } image_filter resize $width $height; image_filter_jpeg_quality 75; image_filter_buffer 100M; # 缩略图配置结束 } #PROXY-END/ 5.验证 ,登录 http://192.168.188.40:19001 账号密码 minio / minio123
2024年05月26日
22 阅读
0 评论
0 点赞
2024-05-25
Linux命令记录
1. 互传文件scp -r /www/wwwroot root@ip:/www/wwwroot
2024年05月25日
24 阅读
0 评论
0 点赞
2024-05-23
gitlab的备份和迁移
创建备份数据docker exec -t gitlab-ee gitlab-rake gitlab:backup:create恢复备份数据docker exec -i -t gitlab-ee bashgitlab-rake gitlab:backup:restore BACKUP=/var/opt/gitlab/backups/1716450303_2024_05_23_17.0.1-ee
2024年05月23日
18 阅读
0 评论
0 点赞
2024-05-21
简单几步将Ubuntu 22.04 LTS升级到Ubuntu 24.04 LTS
简单几步将Ubuntu 22.04 LTS升级到Ubuntu 24.04 LTSUbuntu 24.04 LTS稳定版本(代号Noble Numbat )于2024年4月25日正式发布,如果你想知道其中的内容,现在可以从较低版本升级到该版本进行功能测试。就像每个新的Ubuntu版本一样,Ubuntu 24.04附带了最新功能,包括最新、最好的软件,例如Linux内核、GNOME 46和更新的工具链。想了解更多功能更新,可以从Ubuntu发行说明中找到有关更新内容。重要的是,Ubuntu 24.04 LTS将为Ubuntu Desktop、Ubuntu Server和Ubuntu Core提供为期5年的支持,也就是将会持续到2029年4月份。在本文当中,小编主要介绍如何将Ubuntu 22.04系统升级到最新Ubuntu 24.04 LTS,一起来看看注意的过程步骤吧!检查系统版本:lsb_release -a第1步:备份Ubuntu数据要在升级到Ubuntu 24.04之前,务必将Ubuntu 22.04上的数据备份到外部驱动器,可以按照以下几个步骤进行操作。首先,插入外部存储设备(例如USB驱动器或外部硬盘驱动器),并确保你的计算机可以识别它。打开终端并输入“ lsblk ”以在列表中查找你的外部驱动器,该驱动器可能类似于“/ dev/sdb1 ”。识别外部驱动器之后,可以通过运行df命令并在输出中查找与外部驱动器标识符(例如/dev/sdb1 )对应的条目来找到其挂载(mount)点。挂载点将列在该条目的第二列中,通常看起来像“ /mnt/external ”或“ /media/username/external ”。此挂载点是你的外部驱动器当前连接并可在系统中访问的位置。使用rsync命令将主目录备份到外部驱动器:rsync -av --progress /home/username /path/to/external/drive使用tar命令创建主目录的压缩存档并将其保存到外部驱动器:tar -cvzf /path/to/external/drive/backup_home.tar.gz /home/username注意:将/path/to/external/drive替换为外部驱动器的路径,将/home/username替换为主目录的路径。此外,你还可以使用Deja Dup或Timeshift等图形备份工具将数据备份到外部驱动器。选择适合自己的方式就行,不管选择哪种,只要能够备份好数据就行。第2步:准备Ubuntu系统升级在开始升级系统之前,确保需要任何更新非常重要。之后,更新并升级你当前的软件包。升级完成后,重新启动系统,以便所有更改都能正常工作。sudo apt list --upgradable sudo apt update && sudo apt upgrade -y reboot第三步:将 Ubuntu22.04 LTS升级到24.04 LTS如果通过SSH升级,请确保在ufw防火墙上打开TCP端口1022,以便在升级过程中保持稳定的连接:sudo ufw allow 1022/tcp如果你可以物理访问Ubuntu桌面并在本地升级,则无需打开任何端口,只需安装Update Manager Core工具,这将确保安装升级所需的所有工具:sudo apt install update-manager-core安装Update Manager Core之后,通过输入以下命令启动升级过程:sudo do-release-upgrade -d如果系统没有找到新版本,并且出现以下错误的话:Checking for a new Ubuntu release There is no development version of an LTS available. To upgrade to the latest non-LTS development release set Prompt=normal in /etc/update-manager/release-upgrades.出现此错误消息表明你正在尝试升级到不存在的Ubuntu LTS版本的开发版本。以下是发生的情况以及解决方法:Ubuntu版本有两种主要类型:LTS(长期支持)和非LTS(开发版本)。无法直接从LTS版本(例如22.04 LTS)升级到开发版本(当前不可用)。系统通知你当前LTS ( 24.04 LTS ) 尚无开发版本。由于你想从Ubuntu 22.04 LTS升级到最新的LTS版本 ( 24.04 LTS ),因此需要执行以下操作。打开/etc/update-manager/release-upgrades升级配置文件,并将“ Prompt ”的值更改为“ normal ”,这样可以确保你收到有关升级的通知,并可以选择是否继续。sudo nano /etc/update-manager/release-upgrades现在,使用以下命令再次启动升级过程:sudo do-release-upgrade这会将你带到Ubuntu 23.10版本,目前你无法使用do-release-upgrade命令直接从Ubuntu 22.04 LTS升级到24.04 LTS,因为官方升级路径尚不可用。所以,要升级到Ubuntu 24.04,必须先更新到Ubuntu 23.10。然后,可以从那里升级到Ubuntu 24.04。现在按照屏幕上的说明升级到Ubuntu 23.10版本并重新启动系统:reboot再次打开/etc/update-manager/release-upgrades升级配置文件,将“ Prompt ”的值更改为“ lts ”:sudo nano /etc/update-manager/release-upgrades最后输入以下命令,然后继续按照指南的其余部分从版本23.10升级到24.04 LTS:sudo do-release-upgrade -d第4步:删除过时的软件包要在升级Ubuntu后删除过时的软件包以确保系统清洁,可以使用以下命令:sudo apt autoremove运行上述命令将删除升级后系统不再需要的任何过时的软件包,这有助于释放磁盘空间并保持系统整洁和高效。第5步:在Ubuntu上启用第三方存储库要启用第三方存储库,需要在/etc/apt/sources.list.d/目录下找到在升级过程中可能已禁用的第三方存储库。接下来,取消注释并删除#相应文件中每个存储库每行开头的符号。通过运行以下命令确认第三方存储库已启用,以确保必要的存储库处于活动状态:ls -l /etc/apt/sources.list.d/通过执行这些步骤,你可以在从Ubuntu 22.04升级后在Ubuntu 24.04上成功启用第三方存储库。小结通过以下几个步骤就能够成功将Ubuntu版本从22.04升级到24.04,相对来说还是比较近简单的。需要注意的是,在升级之前,一定要做好备份工作。另外,Ubuntu 22.04无法直接升级,需要先升级到Ubuntu 23.10,然后从Ubuntu 23.10升级到Ubuntu 24.04。
2024年05月21日
24 阅读
0 评论
0 点赞
2024-05-11
Flask项目的一些封装
封装传入的参数main.py文件from base.views import asapi from flask import Flask, request, jsonify from flask_cors import CORS from base.views import ApiException as ex app = Flask(__name__) # CORS(app, resources={r"/*": {"origins": ["http://localhost:63343"]}}) CORS(app, resources={r"/*": {"origins": "*"}}) def checker1(param): # print("checker", param) return True @app.route("/test", methods=['get', 'post']) @asapi(checker=checker1) def test(param): return param if __name__ == '__main__': # en = Encipher() # res = en.getDatas({"1": "123"}) # print(res) # print(en.encode_data(res)) app.run( host="0.0.0.0", port=6003, debug=False )main.py文件下,新建一个base目录,创建文件views.py,写入下面内容from flask import request, jsonify from lxml.html.clean import clean_html import inspect class SiteException(Exception): def __init__(self, message=None, code=None): self.message = message self.code = code def to_json(self): pass def __str__(self): # return jsonify({"code": self.code, "msg": self.message}) return self.message class ApiException(SiteException): def __init__(self, message, code=1001): self.message = message self.code = code def to_json(self): return {"code": self.code, "msg": self.message} # return self.message def raiseApiEx(e, c=1001): raise ApiException(e, c) def asapi(a=None, checker=None): def param_handler(func): def wrapper(*args, **kwargs): def __func(**kvargs): try: req = kvargs.get("param") if checker and not checker(req): raiseApiEx('检查不通过') params = req datas = {} for k, v in list(params.items()): if v == 'undefined': # 排除JS值空 params[k] = '' for k in list(params.keys()): v = params[k] if isinstance(v, str) and '<' in v and '>' in v: lv = v.lower() if 'script' in lv or 'cookie' in lv: params[k] = clean_html(v) # arginfos = getattr(func, 'arginfos') arginfos = inspect.signature(func).parameters for param_name, param_info in arginfos.items(): if param_name != "param" and param_name not in params: params[param_name] = param_info.default if param_name == "param": datas['param'] = params elif param_info.default == inspect.Parameter.empty and param_name not in params: raise raiseApiEx(f"{func.__name__}缺少参数:{param_name}") else: datas[param_name] = params.get(param_name, param_info.default) res = func(**datas) return apiReaspone(en.getDatas(res)) except ApiException as e: return jsonify(e.to_json()) param = dict(request.values.items()) setattr(__func, 'checker', checker) kwargs.setdefault("param", param) # 在这里可以对参数进行处理,比如验证、转换等操作 # 将参数传递给路由处理函数 return __func(**kwargs) return wrapper return param_handler def apiReaspone(data): return jsonify({"code": 200, "data": data})
2024年05月11日
20 阅读
0 评论
0 点赞
2024-05-07
supervisor的安装和使用
安装pip install supervisor自定义服务配置文件echo_supervisord_conf > /etc/supervisord.conf配置文件的大概内容[unix_http_server] file=/tmp/supervisor.sock ; the path to the socket file ;chmod=0700 ; socket file mode (default 0700) ;chown=nobody:nogroup ; socket file uid:gid owner ;username=user ; default is no username (open server) ;password=123 ; default is no password (open server) [supervisord] logfile=/tmp/supervisord.log ; main log file; default $CWD/supervisord.log logfile_maxbytes=50MB ; max main logfile bytes b4 rotation; default 50MB logfile_backups=10 ; # of main logfile backups; 0 means none, default 10 loglevel=info ; log level; default info; others: debug,warn,trace pidfile=/tmp/supervisord.pid ; supervisord pidfile; default supervisord.pid [supervisorctl] serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket ;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket ;username=chris ; should be same as in [*_http_server] if set ;password=123 ; should be same as in [*_http_server] if set ;prompt=mysupervisor ; cmd line prompt (default "supervisor") ;history_file=~/.sc_history ; use readline history if available ;[program:theprogramname] ;command=/bin/cat ; the program (relative uses PATH, can take args) ;[group:thegroupname] ;programs=progname1,progname2 ; each refers to 'x' in [program:x] definitions ;priority=999 ; the relative start priority (default 999) ;[include] ;files = relative/directory/*.ini对于上述配置参数,可以按照具体的需求进行自定义,大多数参数可以保持默认设置。但是为了方便多个项目的统一管理,需要启用 [include] 参数。该参数用于将指定文件包含到配置中,通过这种方式来 "扩展" 服务配置文件。创建配置目录,并修改 files 参数 :mkdir /etc/supervisord.d[include] files = /etc/supervisord.d/*.ini自定义应用配置文件假设现在有一个测试项目 (test),里面有个 test.py 脚本需要持久化运行。现在切换到项目目录 (/root/test),并按照以下格式创建应用配置文件。{porject_name}.ini配置项目的进程启动参数 :; /root/test/test.ini [program:test] command=python -u ./test.py ; 运行命令 directory=/root/test/ ; 运行目录 redirect_stderr=true ; 将 stderr 重定向到 stdout stdout_logfile=/root/test/test.log ; 日志文件输出路径 autorestart=true ; 用于控制是否在 supervisord 进程启动时同时启动 (默认为 true) startsecs=3 ; 是与自动重启相关的另一个配置参数。其作用是用于判断进程是否启动成功,只有当目标进程运行时间大于该配置时,才会判断成成功。 startretries=3 ; 参数需要与 startsecs 参数配合使用,用于控制目标进程的重启尝试次数,并且每次重试花费的时间间隔越来越长。可以通过以下代码测试一下: stdout_logfile=/supervisor/log/win_server.out.log ; 指定标准输出流的日志文件路径。 stderr_logfile=/supervisor/log/win_server.err.log ; 错误日志文件输出路径 stdout_logfile_maxbytes=2MB ; 单个日志文件的最大字节数,当超过该值时将对日志进行切分。 stderr_logfile_maxbytes=2MB ; 错误日志文件最大2MB user=root ; 使用什么用户运行 priority=999 ; 优先级,数值越小越先启动 numprocs=1 ; 用于指定运行时的进程实例数量,需要与 process_name 参数配合使用。 process_name=%(program_name)s_%(process_num)02d使用# 宝塔面板中: # 使用软链接链接到user/bin下面,这样可以在命令行直接使用 ln -s /www/server/panel/pyenv/bin/supervisorctl /usr/bin/supervisorctl # 进入到管理界面 supervisorctl # 查看所有子进程状态 status # 查看单个子进程的状态 status 子进程 # 关闭单个子进程 stop 子进程 # 关闭所有子进程 stop all # 启动单个子进程 start 子进程 # 启动所有子进程 start all # 重启单个子进程 restart 子进程
2024年05月07日
32 阅读
0 评论
0 点赞
2024-04-30
如何在 Debian 10 中配置 Chroot 环境的 SFTP 服务
如何在 Debian 10 中配置 Chroot 环境的 SFTP 服务SFTP 意思是“ 安全文件传输协议(Secure File Transfer Protocol)” 或 “ SSH 文件传输协议(SSH File Transfer Protocol)”,它是最常用的用于通过 ssh 将文件从本地系统安全地传输到远程服务器的方法,反之亦然。sftp 的主要优点是,除 openssh-server 之外,我们不需要安装任何额外的软件包,在大多数的 Linux 发行版中,openssh-server 软件包是默认安装的一部分。sftp 的另外一个好处是,我们可以允许用户使用 sftp ,而不允许使用 ssh 。当前发布的 Debian 10 代号为 ‘Buster’,在这篇文章中,我们将演示如何在 Debian 10 系统中在 “监狱式的” Chroot 环境中配置 sftp。在这里,Chroot 监狱式环境意味着,用户不能超出各自的家目录,或者用户不能从各自的家目录更改目录。下面实验的详细情况:OS = Debian 10IP 地址 = 192.168.56.151让我们跳转到 SFTP 配置步骤,步骤 1、使用 groupadd 命令给 sftp 创建一个组打开终端,使用下面的 groupadd 命令创建一个名为的 sftp_users 组:groupadd sftp_users步骤 2、添加用户到组 sftp_users 并设置权限假设你想创建新的用户,并且想添加该用户到 sftp_users 组中,那么运行下面的命令,useradd -m -G sftp_users <用户名> 让我们假设用户名是 jonathan:useradd -m -G sftp_users jonathan 使用下面的 chpasswd 命令设置密码:echo "jonathan:<输入密码>" | chpasswd 假设你想添加现有的用户到 sftp_users 组中,那么运行下面的 usermod 命令,让我们假设已经存在的用户名称是 chris:usermod -G sftp_users chris 现在设置用户所需的权限:chown root /home/jonathan /home/chris/ 在各用户的家目录中都创建一个上传目录,并设置正确地所有权:mkdir /home/jonathan/upload mkdir /home/chris/upload chown jonathan /home/jonathan/upload chown chris /home/chris/upload 注意: 像 Jonathan 和 Chris 之类的用户可以从他们的本地系统上传文件和目录。步骤 3、编辑 sftp 配置文件 /etc/ssh/sshd_config正如我们已经陈述的,sftp 操作是通过 ssh 完成的,所以它的配置文件是 /etc/ssh/sshd_config,在做任何更改前,我建议首先备份文件,然后再编辑该文件,接下来添加下面的内容:cp /etc/ssh/sshd_config /etc/ssh/sshd_config-org vim /etc/ssh/sshd_config ...... #Subsystem sftp /usr/lib/openssh/sftp-server Subsystem sftp internal-sftp Match Group sftp_users ChrootDirectory /home/%u ForceCommand internal-sftp AllowTcpForwarding no X11Forwarding no ...... 保存并退出文件。为使上述更改生效,使用下面的 systemctl 命令来重新启动 ssh 服务:systemctl restart sshd 在上面的 sshd_config 文件中,我们已经注释掉了以 Subsystem 开头的行,并添加了新的条目 Subsystem sftp internal-sftp 和新的行。而Match Group sftp_users –> 它意味着如果用户是 sftp_users 组中的一员,那么将应用下面提到的规则到这个条目。ChrootDierctory %h –> 它意味着用户只能在他们自己各自的家目录中更改目录,而不能超出他们各自的家目录。或者换句话说,我们可以说用户是不允许更改目录的。他们将在他们的目录中获得监狱一样的环境,并且不能访问其他用户的目录和系统的目录。ForceCommand internal-sftp –> 它意味着用户仅被限制到只能使用 sftp 命令。步骤4、测试和验证sftpsftp -P ssh端口 username@ip
2024年04月30日
20 阅读
0 评论
0 点赞
2024-04-11
js将页面弄成pdf
// 使用html2pdf这个js,js公共cdn,https://staticfile.org/https://cdn.staticfile.net/html2pdf.js/0.10.1/html2pdf.bundle.js<script src="https://cdn.staticfile.net/html2pdf.js/0.10.1/html2pdf.bundle.js"></script> let url = "https://0.0.0.0" fetch(url) .then(response => response.text()) .then(data => { var element = document.createElement('div'); element.innerHTML = data; html2pdf(element, { margin: [1, 1, 1, 1], filename: sup.name + "-签署的协议.pdf", pagebreak: {mode: "avoid-all"}, jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' } }); console.log('PDF generated successfully'); }) .catch(error => { console.error('Error:', error); });
2024年04月11日
15 阅读
0 评论
0 点赞
1
2
...
6