首页
关于
Search
1
同步本地Markdown至Typecho站点
54 阅读
2
微服务
38 阅读
3
苍穹外卖
27 阅读
4
JavaWeb——后端
24 阅读
5
消息队列MQ
18 阅读
后端学习
项目
杂项
科研
论文
默认分类
登录
找到
11
篇与
杂项
相关的结果
2025-09-08
K8S
Kubernetes (K8S) Kubernetes 是一个开源的容器编排平台,用于自动化部署、扩缩容(Pod 数量多了/少了自动调整)和自愈(坏掉的 Pod 会被自动重建) 基本架构 一个 Kubernetes 集群 (Cluster) = 控制平面 + 工作节点 的组合。要使用K8S,要先搭建集群,deployment.yaml 和 service.yaml 要提交到 K8S 集群,由它调度和运行。 控制平面 (Control Plane) 负责管理整个集群,不直接跑应用。 组件 作用 比喻 API Server 接收命令(kubectl)、提供统一接口 前台服务员 etcd 存储集群所有状态(配置、Pod 列表等) 账本/数据库 Scheduler 决定 Pod 跑在哪个 Node 上 领班 Controller Manager 保证实际状态符合预期(补 Pod、重建失败的 Pod) 经理 工作节点 (Worker Nodes) 实际跑应用容器。 组件 作用 Kubelet 负责跟 API Server 沟通,并启动/管理容器 容器运行时 运行容器(Docker、containerd) Kube-Proxy 管理网络规则,实现 Service 的负载均衡 graph TD A[控制平面] --> B[Node 1] A --> C[Node 2] A --> D[Node 3] B --> E[Pod] B --> F[Pod] C --> G[Pod] D --> H[Pod] K8S 核心概念 Pod 最小运行单元,一个 Pod 里可以有 1 个或多个容器。 共享网络和存储空间 Deployment 管 Pod 的「副本数」和「版本」。 支持滚动更新、回滚 Service 提供稳定的网络入口(因为 Pod IP 会变)。 负载均衡到一组 Pod。 ConfigMap & Secret ConfigMap:存储配置信息(非敏感)。 Secret:存储敏感信息(密码、Token),会加密。 基本使用方式 Deployment(定义 Pod 模板 + 副本数) apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: replicas: 3 # 要 3 个 Pod selector: matchLabels: app: my-app template: # Pod 模板 metadata: labels: app: my-app #给 Pod 打标签,Service 用 selector 找到这些 Pod 做负载均衡 spec: containers: - name: my-app #Pod名 image: my-registry/my-app:v1 # ← 指向 CI 推送后的镜像(仓库/名称:标签) ports: - containerPort: 8080 #容器对外提供服务的端口 Pod名可能是:my-app-6f7c9d7c5d-abcde,它里面的容器名:my-app 映射关系: kind: Deployment → 创建一个「Pod 管理器」 replicas: 3 → 保证始终有 3 个 Pod template → Pod 的样子(运行哪个镜像、开哪个端口) Service(提供统一访问入口) apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: my-app # 找到所有带 app=my-app 标签的 Pod ports: - port: 80 # Service 入口端口 targetPort: 8080 # Pod 里容器的端口 type: LoadBalancer # 暴露给外部访问 映射关系: selector → 绑定到 Deployment 创建的 Pod,根据 Pod 的标签(my-app) ports → 用户访问 80 端口,会转发到 Pod 的 8080 type: LoadBalancer → 提供一个外部 IP 供用户访问 典型工作流程 sequenceDiagram 开发者->>Git: 提交代码 Git->>CI/CD: 触发构建 CI/CD->>镜像仓库: 构建Docker镜像 CI/CD->>K8S: kubectl apply K8S->>K8S: 创建/更新Pod K8S->>K8S: 健康检查 K8S->>用户: 服务可用 sequenceDiagram 开发者->>API Server: kubectl apply -f xxx.yaml API Server->>etcd: 写入期望状态 API Server->>Scheduler: 请求调度 Scheduler->>Node: 分配 Pod 到合适的节点 Node->>Kubelet: 启动容器 Controller Manager->>Cluster: 监控状态并修复 Service->>用户: 提供统一访问入口 👉 过程总结: 提交 YAML → API Server 接收并存到 etcd。 Scheduler 决定 Pod 去哪个 Node。 Node 上的 Kubelet 把容器启动。 Controller Manager 盯着数量,缺了就补。 Service 统一出口,用户不用关心 Pod IP。 常用操作 前提是1:集群必须已经搭好(minikube/kind/k3s/云厂商的 K8S)。 2:kubectl 已经配置好 kubeconfig 3:镜像能拉取到 如果是公有镜像(比如 Docker Hub),直接写就行。 如果是私有仓库,需要配 imagePullSecrets。 # 部署应用 kubectl apply -f deployment.yaml kubectl apply -f service.yaml # 查看集群资源 kubectl get pods -o wide kubectl get deployments kubectl get services # 扩缩容 kubectl scale deployment/my-app --replicas=5 # 滚动更新 kubectl set image deployment/my-app my-app=my-registry/my-app:v2 # 回滚 kubectl rollout undo deployment/my-app
杂项
zy123
9月8日
0
1
0
2025-09-06
CICD
CI/CD 自动部署项目 使用Gitea Actions 1)启用Gitea Actions: 编辑你的Gitea服务器配置文件 app.ini(通常位于 /etc/gitea/或 Gitea 安装目录),添加: [actions] ENABLED = true 然后重启Gitea服务。 2)在部署服务器上安装Runner: # 1. 下载并安装 act_runner (需要sudo) sudo wget https://gitea.com/gitea/act_runner/releases/download/v0.2.10/act_runner-0.2.10-linux-amd64 -O /usr/local/bin/act_runner sudo chmod +x /usr/local/bin/act_runner # 2. 为Runner创建专用工作目录(推荐使用绝对路径) sudo mkdir -p /opt/gitea-runner sudo chown $USER:$USER /opt/gitea-runner # 将目录所有权给当前用户 cd /opt/gitea-runner # 3. 注册Runner(重要:必须添加labels标签) act_runner register --no-interactive \ --instance https://你的gitea域名.com \ --token <你的令牌> \ --name my-runner \ --labels self-hosted,linux # 这个标签必须与工作流文件中的runs-on匹配 # 4. 启动Runner(后台运行) nohup act_runner daemon > runner.log 2>&1 & # 5. 查看运行状态和日志 tail -f runner.log ps aux | grep act_runner 3)令牌获取: 如果你想给整个实例用 → 站点管理员设置 → Actions → Runners。 如果只想给某个仓库用 → 进入该仓库 → Settings → Actions → Runners。 点击 New Runner,系统会生成一个 TOKEN。 例如:abcdef1234567890 还是设置整个实例好!! 4)将act_runner注册为服务自启动 sudo vim /etc/systemd/system/act_runner.service 写入以下内容: [Unit] Description=Gitea Actions Runner After=network.target [Service] ExecStart=/usr/local/bin/act_runner daemon WorkingDirectory=/opt/gitea-runner User=zy123 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ExecStart 指向你安装的 act_runner 路径(你已经放在 /usr/local/bin/ 了)。 WorkingDirectory 可以写你打算存放 Runner 缓存的目录(比如 /home/zy123/act_runner,你已经在这里 register 过了)。 User=zy123 保证 Runner 以你当前用户运行,而不是 root。 重新加载 systemd 配置: sudo systemctl daemon-reexec 启动并开机自启: sudo systemctl enable --now act_runner 查看运行状态: systemctl status act_runner 5)在后端仓库根目录下,新建目录和文件: .gitea/workflows/deploy.yml 写入以下内容: name: Deploy Backend on: push: branches: [ "master" ] # master 分支推送时触发 jobs: build-and-deploy: runs-on: self-hosted steps: - name: Checkout code uses: actions/checkout@v3 - name: Create application-local.yml run: | mkdir -p src/main/resources/ cat << 'EOF' > src/main/resources/application-local.yml ${{ secrets.APPLICATION_LOCAL_YML }} EOF - name: Build and restart smile-picture run: | cd docs/tags/picture-v1.0 docker compose -f docker-compose-app-v1.0.yml build smile-picture-backend docker compose -f docker-compose-app-v1.0.yml up -d smile-picture-backend - name: Cleanup dangling images run: docker image prune -f 特别注意,application-local没有用git管理,把它存在了Actions的密钥中: 然后deploy.yml中可以把里面的内容复制过去。 6)工作原理 1.Runner 接收任务 当你 push 到 main 分支时: Gitea 会触发 workflow(.gitea/workflows/deploy.yml)。 服务器上的 act_runner 会接收到这个任务,并开始执行 jobs.build-and-deploy。 2.actions/checkout@v3 这一行的作用是:它会把你刚刚 push 的最新代码 完整克隆 到 Runner 的工作目录。 /home/<你的用户>/actions-runner/_work/<repo名>/<repo名>/ 所以,这时候你的项目在 Runner 的临时目录里已经是最新代码了,不需要 git pull。 3.后续 cd docs/tag/group-buy-v3.0 都是在 这个临时目录 里执行的。 相当于你在服务器上的临时副本中: 用 docker compose build 构建镜像 用 docker compose up -d 启动/更新容器 4.Runner 每次执行 workflow 时,工作目录都会 重新 checkout 最新代码。 默认不会自动清理旧目录,但可以在 workflow 里加 actions/checkout 的参数来控制,比如 clean: true。. 7)git push之后
杂项
zy123
9月6日
0
3
0
2025-07-30
mermaid画图
mermaid画图 graph TD A[多智能体随机网络结构分析] --> B[多智能体协同学习与推理] A --> A1["谱参数实时估算"] A1 --> A11["卡尔曼滤波"] A1 --> A12["矩阵扰动理论"] A1 --> A13["输出:谱参数"] A --> A2["网络拓扑重构"] A2 --> A21["低秩分解重构"] A2 --> A22["聚类量化"] A2 --> A23["输出:邻接矩阵、特征矩阵"] graph TD B[多智能体协同学习与推理] B --> B1["联邦学习、强化学习"] B1 --> B11["谱驱动学习率调整"] B1 --> B12["自适应节点选择策略"] B --> B2["动态图神经网络"] B2 --> B21["动态图卷积设计"] B2 --> B22["一致性推理"] graph TD %% 颜色和样式定义 classDef startEnd fill:#e6ffe6,stroke:#333,stroke-width:2px classDef operation fill:#fff,stroke:#000,stroke-width:1px classDef decision fill:#ffcccc,stroke:#000,stroke-width:1px classDef update fill:#ccffcc,stroke:#000,stroke-width:1px %% 节点定义(严格按图片顺序) A([开始]):::startEnd B[交易信息\n外部订单号]:::operation C{判断是否为锁单订单}:::decision D[查询拼团组队信息]:::operation E[更新订单详情\n状态为交易完成]:::update F[更新拼团组队进度]:::update G{拼团组队完结\n目标量判断}:::decision H[写入回调任务表]:::operation I([结束]):::startEnd %% 流程连接(完全还原图片走向) A --> B B --> C C -->|是| D D --> E E --> F F --> G G -->|是| H H --> I C -->|否| I G -->|否| I %% 保持原图连接线样式 linkStyle 0,1,2,3,4,5,6,7,8 stroke-width:1px graph TD A[用户发起退单请求] --> B{检查拼团状态} B -->|拼团未完成| C1[场景1:拼团中退单] C1 --> D1{是否已支付?} D1 -->|未支付| E1[取消订单] E1 --> F1[更新订单状态为2] F1 --> G1[通知拼团失败] G1 --> H1[退单完成] D1 -->|已支付| I1[发起退款] I1 --> F1 B -->|拼团已完成| C2[场景2:完成后退单] C2 --> D2{是否超时限?} D2 -->|未超时| E2[发起退款] E2 --> F2[更新订单状态] F2 --> H1 D2 -->|超时| G2[退单失败] style A fill:#f9f,stroke:#333 style B fill:#66f,stroke:#333 style C1 fill:#fbb,stroke:#f66 style C2 fill:#9f9,stroke:#090 flowchart LR %% ===================== 左侧:模板模式块 ===================== subgraph Template["设计模式 - 模板"] direction TB SM["StrategyMapper 策略映射器"] SH["StrategyHandler 策略处理器"] ASR["AbstractStrategyRouter<T, D, R> 策略路由抽象类"] SM -->|实现| ASR SH -->|实现| ASR end %% ===================== 右侧:策略工厂与支持类 ===================== DASFactory["DefaultActivityStrategyFactory 默认的拼团活动策略工厂"] AGMS["AbstractGroupBuyMarketSupport 功能服务支撑类"] DASFactory --> AGMS AGMS -->|继承| ASR %% ===================== 业务节点链路 ===================== Root["RootNode 根节点"] Switch["SwitchRoot 开关节点"] Market["MarketNode 营销节点"] End["EndNode 结尾节点"] Other["其他节点"] AGMS --> Root Root --> Switch Switch --> Market Market --> End Switch -.-> Other Other --> End %% ===================== 样式(可选) ===================== classDef green fill:#DFF4E3,stroke:#3B7A57,stroke-width:1px; classDef red fill:#E74C3C,color:#fff,stroke:#B03A2E; classDef purple fill:#7E60A2,color:#fff,stroke:#4B3B6B; classDef blue fill:#3DA9F5,color:#fff,stroke:#1B6AA5; class SM,SH,Root,Switch,Market,End,Other green; class DASFactory red; class AGMS purple; class ASR blue; style Template stroke-dasharray: 5 5; sequenceDiagram participant A as 启动时 participant B as BeanPostProcessor participant C as 管理后台 participant D as Redis Pub/Sub participant E as RTopic listener participant F as Bean 字段热更新 A->>B: 扫描 @DCCValue 标注的字段 B->>B: 写入默认值 / 读取 Redis B->>B: 注入字段值 B->>B: 缓存 key→Bean 映射 A->>A: Bean 初始化完成 C->>D: publish("myKey,newVal") D->>E: 订阅频道 "dcc_update" E->>E: 收到消息,更新 Redis E->>E: 从 Map 找到 Bean E->>E: 反射注入新值到字段 E->>F: Bean 字段热更新完成 sequenceDiagram participant A as 后台/系统 participant B as Redis Pub/Sub participant C as DCC监听器 participant D as Redis数据库 participant E as 反射更新字段 participant F as Bean实例 A->>B: 发布消息 ("cutRange:50") B->>D: 将消息 "cutRange:50" 写入 Redis B->>C: 触发订阅者接收消息 C->>D: 更新 Redis 中的 "cutRange" 配置值 C->>F: 根据映射找到对应的 Bean C->>E: 通过反射更新 Bean 中的字段 E->>C: 更新成功,字段值被同步 C->>A: 配置变更更新完成 flowchart LR A[请求进入链头 Head] --> B[节点1: 日志LogLink] B -->|继续| C[节点2: 权限AuthLink] B -->|直接返回/终止| R1[返回结果] C -->|通过→继续| D[节点3: 审批ApproveLink] C -->|不通过→终止| R2[返回失败结果] D --> R3[返回成功结果] classDef node fill:#eef,stroke:#669; classDef ret fill:#efe,stroke:#393; class A,B,C,D node; class R1,R2,R3 ret; flowchart LR subgraph mall["小型支付商城"] style mall fill:#ffffff,stroke:#333,stroke-width:2 A[AliPayController<br/>发起退单申请]:::blue C[订单状态扭转<br/>退单中]:::grey E[RefundSuccessTopicListener<br/>接收MQ消息<br/>执行退款和订单状态变更]:::green end subgraph pdd["拼团系统"] style pdd fill:#ffffff,stroke:#333,stroke-width:2 B[MarketTradeController<br/>接收退单申请]:::yellow D[TradeRefundOrderService<br/>退单策略处理]:::red F[TradeRepository<br/>发送MQ消息]:::purple G([MQ消息队列<br/>退单成功消息]):::orange H[RefundSuccessTopicListener<br/>接收MQ消息<br/>恢复库存]:::green end A -- "1. 发起退单请求" --> B B -- "2. 处理退单" --> D D -- "3. 发送MQ消息" --> F F -- "4. 发布消息 (异步+本地消息表补偿)" --> G F -- "5. 返回结果" --> C G -- "6. 消费消息 (恢复库存)" --> H G -. "7. 消费消息 (执行退款)" .-> E classDef blue fill:#dbe9ff,stroke:#6fa1ff,stroke-width:1; classDef grey fill:#e5e5e5,stroke:#9e9e9e,stroke-width:1; classDef green fill:#d6f2d6,stroke:#76b076,stroke-width:1; classDef yellow fill:#fef3cd,stroke:#f5c700,stroke-width:1; classDef red fill:#f8d7da,stroke:#e55353,stroke-width:1; classDef purple fill:#e4dbf9,stroke:#9370db,stroke-width:1; classDef orange fill:#ffecca,stroke:#ffa500,stroke-width:1; sequenceDiagram participant Client as 前端 participant WS as WebSocket 服务器 participant Auth as 权限校验 participant Dispatcher as 消息分发器 participant Handler as 消息处理器 Client->>WS: 请求建立 WebSocket 连接 WS->>Auth: 校验用户权限 Auth-->>WS: 校验通过,保存用户和图片信息 WS-->>Client: 连接成功 Client->>WS: 发送消息(包含消息类型) WS->>Dispatcher: 根据消息类型分发 Dispatcher->>Handler: 执行对应的消息处理逻辑 Handler-->>Dispatcher: 返回处理结果 Dispatcher-->>WS: 返回处理结果 WS-->>Client: 返回处理结果给客户端 Client->>WS: 断开连接 WS-->>Client: 删除 WebSocket 会话,释放资源 sequenceDiagram participant Client as Client(浏览器) participant WS as WebSocket Endpoint participant Producer as PictureEditEventProducer participant RB as RingBuffer participant Worker as PictureEditEventWorkHandler participant Handler as PictureEditHandler Client->>WS: 发送 PictureEditRequestMessage WS->>Producer: publishEvent(msg, session, user, pictureId) Producer->>RB: next() 获取序号,写入事件字段 Producer->>RB: publish(sequence) 发布 RB-->>Worker: 回调 onEvent(event) Worker->>Worker: 解析 type -> PictureEditMessageTypeEnum alt ENTER_EDIT Worker->>Handler: handleEnterEditMessage(...) else EXIT_EDIT Worker->>Handler: handleExitEditMessage(...) else EDIT_ACTION Worker->>Handler: handleEditActionMessage(...) else 其他/异常 Worker->>WS: sendMessage(ERROR 响应) end Worker-->>Client: 业务处理后的响应(通过 WS) sequenceDiagram participant Client as WebSocket Client participant IO as WebSocket I/O线程 participant Biz as 业务逻辑(耗时) Client->>IO: 收到消息事件(onMessage) IO->>Biz: 执行业务逻辑(耗时3s) Biz-->>IO: 返回结果 IO->>Client: 发送响应 Note over IO: I/O线程被业务阻塞3s 不能处理其他连接的消息 sequenceDiagram participant Client as WebSocket Client participant IO as WebSocket I/O线程 participant Disruptor as RingBuffer队列 participant Worker as Disruptor消费者线程 participant Biz as 业务逻辑(耗时) Client->>IO: 收到消息事件(onMessage) IO->>Disruptor: 发布事件(快速) Disruptor-->>IO: 立即返回 IO->>Client: (继续处理其他连接消息) Worker->>Biz: 异步执行业务逻辑(耗时3s) Biz-->>Worker: 返回结果 Worker->>Client: 通过WebSocket发送响应 flowchart TD A[客户端发起WebSocket连接] --> B[HTTP握手阶段] B --> C[WsHandshakeInterceptor.beforeHandshake] C -->|校验失败| D[拒绝握手 连接关闭] C -->|校验成功| E[建立WebSocket连接] E --> F[PictureEditHandler] F --> G[处理WebSocket消息 收发数据] flowchart TD A([接收请求]) --> B{查询本地缓存 Caffeine} B -- 命中 --> C[返回本地缓存数据] C --> End1(((结束))) B -- 未命中 --> D{查询分布式缓存 Redis} D -- 命中 --> E[更新本地缓存] E --> F[返回 Redis 缓存数据] F --> End2(((结束))) D -- 未命中 --> G[查询数据库] G --> H[更新本地缓存和 Redis 缓存] H --> I[返回数据库数据] I --> End3(((结束))) classDiagram class ImageSearchApiFacade { +searchImage(localImagePath) } class GetImagePageUrlApi { +getImagePageUrl(localImagePath) } class GetImageFirstUrlApi { +getImageFirstUrl(imagePageUrl) } class GetImageListApi { +getImageList(imageFirstUrl) } ImageSearchApiFacade --> GetImagePageUrlApi : Calls ImageSearchApiFacade --> GetImageFirstUrlApi : Calls ImageSearchApiFacade --> GetImageListApi : Calls erDiagram 用户 { BIGINT 用户ID VARCHAR 用户名 } 角色 { BIGINT 角色ID VARCHAR 角色名称 VARCHAR 描述 } 权限 { BIGINT 权限ID VARCHAR 权限名称 VARCHAR 描述 } 用户 }o--o{ 角色 : 拥有 角色 }o--o{ 权限 : 赋予 classDiagram class Collection { <<interface>> +add() +remove() +clear() +size() } class Set { <<interface>> } class List { <<interface>> } class Queue { <<interface>> } class Map { <<interface>> } class HashSet { <<class>> } class TreeSet { <<class>> } class ArrayList { <<class>> } class LinkedList { <<class>> } class PriorityQueue { <<class>> } class HashMap { <<class>> } class TreeMap { <<class>> } Collection <|-- Set Collection <|-- List Collection <|-- Queue Set <|-- HashSet Set <|-- TreeSet List <|-- ArrayList List <|-- LinkedList Queue <|-- LinkedList Queue <|-- PriorityQueue Map <|-- HashMap Map <|-- TreeMap sequenceDiagram participant U as 用户 participant O as 下单服务 participant P as 拼团/优惠服务 participant R as 风控/库存校验 U ->> O: 请求锁单(userId, goodsId, activityId, teamId) activate O %% Step 1 幂等查询 O ->> P: 幂等查询(out_trade_no 是否已有锁单) P -->> O: 存在则直接返回该条记录 %% Step 2 拼团人数校验 O ->> P: 校验拼团人数(再次拉取,避免前端滞后) P -->> O: 校验结果 %% Step 3 优惠试算 O ->> P: 优惠试算(activityId, goodsId) P -->> O: 返回拼团优惠价格 %% Step 4 人群限定 O ->> R: 校验是否在目标人群范围 R -->> O: 校验结果(非目标人群直接拒绝) %% Step 5 锁单责任链 O ->> P: 活动有效性校验 O ->> P: 用户参与次数校验 O ->> R: 剩余库存校验 O -->> U: 返回锁单结果(成功/失败) deactivate O flowchart TD A[initialize @PostConstruct] --> B[fetchAllPictureTableNames] B -->|查询 SpaceService| C[组装所有表名 picture + picture_xxx] C --> D[updateShardingTableNodes] D --> E[getContextManager] E --> F[获取 ShardingSphereRuleMetaData] F --> G[更新 ShardingRuleConfiguration.actual-data-nodes] G --> H[alterRuleConfiguration + reloadDatabase] subgraph 动态建表 I[createSpacePictureTable] --> J{space 是否旗舰团队?} J -- 否 --> K[不建表] J -- 是 --> L[SqlRunner 创建新表 picture_xxx] L --> D end flowchart TD %% 定义节点 Publisher[Publisher<br/>消息发布者] Exchange[fanout Exchange<br/>扇形交换机] Queue1[Queue1] Queue2[Queue2] Queue3[Queue3] Consumer1[Consumer1] Consumer2[Consumer2] Consumer3[Consumer3] Msg[msg] %% 消息流向 Publisher -->|发布消息| Exchange Exchange -->|广播消息| Queue1 Exchange -->|广播消息| Queue2 Exchange -->|广播消息| Queue3 Queue1 -->|投递消息| Consumer1 Queue2 -->|投递消息| Consumer2 Queue3 -->|投递消息| Consumer3 %% 确认回执 Consumer1 -->|ack<br/>成功处理,删除消息| Queue1 Consumer2 -->|nack<br/>处理失败,重新投递| Queue2 Consumer3 -->|reject<br/>处理失败并拒绝,删除消息| Queue3 %% 样式定义 classDef publisher fill:#e1f5fe,stroke:#01579b; classDef exchange fill:#d1c4e9,stroke:#4527a0; classDef queue fill:#f8bbd0,stroke:#880e4f; classDef consumer fill:#c8e6c9,stroke:#1b5e20; class Publisher publisher; class Exchange exchange; class Queue1,Queue2,Queue3 queue; class Consumer1,Consumer2,Consumer3 consumer; flowchart TD subgraph 运营 A1[配置拼团] end subgraph 用户 B1[查看商品] end subgraph 用户A/B C1[参与拼团] end %% 运营流程 A1 --> A2[拼团折扣] A2 --> A3[团长优惠] A3 --> A4[人群标签] %% 用户查看拼团 B1 --> B2[查看拼团] B2 --> B3[优惠试算] B3 --> B4[展示拼团] %% 用户参与拼团 C1 --> D1[商品支付 / 折扣支付] D1 --> D2[展示拼团 + 分享] D1 --> D3[拼团系统] D3 --> D4[记录拼团/多人拼团] D4 --> D5[团购回调/回调地址] D3 --> D6[拼团超时/拼团失败] D6 --> D7[发起退单] D7 --> D8[团购回调/回调地址] %% 拼团后逻辑 D1 --> E1[拼团订单 暂不发货] E1 --> E2[免拼下单 直接成单] E2 --> E3[拼团完成 商品发货] D6 --> F1[拼团失败 商品退单] E1 --> E4[直接购买 放弃拼团] E4 --> F1 E3 -->|成功| End1([结束]) F1 -->|失败| End2([结束]) flowchart TD A[Throwable] --> B[Error] A --> C[Exception] B --> D[虚拟机错误<br>VirtualMachineError] B --> E[内存溢出错误<br>OutOfMemoryError] B --> F[栈溢出错误<br>StackOverflowError] C --> G[IOException] C --> H[RuntimeException] C --> I[检查异常<br>Checked Exception<br>(除RuntimeException外的Exception)] G --> J[FileNotFoundException] G --> K[EOFException] H --> L[空指针异常<br>NullPointerException] H --> M[数组越界异常<br>ArrayIndexOutOfBoundsException] H --> N[类型转换异常<br>ClassCastException] H --> O[算术异常<br>ArithmeticException]
杂项
zy123
7月30日
0
6
0
2025-03-21
matlab
matlab笔记 命令行窗口 clc:清屏(命令行窗口) clear all:把命名的变量删掉,不是命令行窗口 命名规则: 变量命名以字母开头,不可以下划线,变量是区分字母大小写的 脚本 %% xxx 注释(百分号+一个空格) % xxx 也是注释 s='a' '"aaaa",字符串 abs(s) 字符s的ascii码,为97 char(97), 输出'a' numtostr(65) ans='65',数字转字符串 length(str),字符串的长度 矩阵 A=[1 2 3 ;4 5 6 ;7 8 9] 分号换行 B=A‘ ,矩阵转置 C=A(:) ,将矩阵拉成一列,按列存储,第一列拼接第二列拼接第三列 D=inv(A) 求逆矩阵 E=zeros(10,5,3) 生成10行5列3维0矩阵 元胞数组 A=cell(1,6),生成1行6列的小格子,每个小格子可以存放各种数据 eye(3),生成3x3的单位阵 A{2}=eye(3),matlab数组从1开始,不是0
杂项
zy123
3月21日
0
3
0
2025-03-21
linux服务器
llinux服务器(以debian为例) 预先准备 域名购买与解析 购买:Low-Cost Domain Names & Hosting from $0.99 | NameSilo 教程:【服务器、域名购买】Namesilo优惠码和域名解析教程(附带服务器购买推荐和注意事项) | 爱玩实验室 DNS解析:可能需等待几分钟生效 买的域名的r2studying.top 这里的HOSTNAME相当于二级域名,如npm.r2studying.top 现改为CloudFlare来做DNS解析,不用namesilo,它有两种模式: Proxied(橙色云朵):当你将某个 DNS 记录设置为 Proxied 时,Cloudflare 会作为反向代理服务器处理该域名的 HTTP/HTTPS 流量。这样做有几个效果: 隐藏真实 IP:用户访问时看到的是 Cloudflare 的 Anycast IP,而不是你服务器的真实 IP,从而提高安全性。 提供 CDN 加速:Cloudflare 会缓存静态资源,并通过全球节点加速内容传输,提升网站响应速度。 附加安全防护:包括 DDoS 防护和 Web 应用防火墙等功能。 DNS Only(灰色云朵):如果你设置为 DNS Only,Cloudflare 只负责 DNS 解析,不会对流量进行代理或处理。也就是说,用户访问时会直接获取并连接到你服务器的真实 IP。 安全组设置 登录云服务器的控制台设置 入站规则 入站规则(Inbound Rules)是指防火墙中用来控制外部流量进入服务器的规则。通过这些规则,你可以指定允许或拒绝哪些类型的网络流量(例如特定协议、端口号、IP地址等)进入你的服务器。 类型 协议端口 源地址 描述 IPv4 TCP : 22 0.0.0.0/0 允许外部访问安全组内实例的SSH(22)端口,用于远程登录Linux实例。 IPv4 TCP : 3389 0.0.0.0/0 允许外部访问安全组内实例的RDP(3389)端口,用于远程登录Windows实例。 IPv4 TCP : 80 0.0.0.0/0 允许外部访问安全组内实例的HTTP(80)端口,用于通过HTTP协议访问网站。 IPv4 TCP : 443 0.0.0.0/0 允许外部访问安全组内实例的HTTPS(443)端口,用于通过HTTPS协议访问网站。 IPv4 TCP : 20-21 0.0.0.0/0 允许通过FTP上传和下载文件。 IPv4 ICMP: 全部 0.0.0.0/0 允许外部使用ping命令验证安全组内实例的网络连通性。 出站规则 出站规则(Outbound Rules)则是指控制服务器向外部发送流量的规则。你可以通过出站规则来限制服务器发出的数据包,比如限制服务器访问某些外部服务或 IP 地址。 凡是服务正常启动但是浏览器上无法访问的,都首先想想防火墙端口是否打开!!! 常用的命令 cat 用于查看文本文件的内容 head 查看前n行 head -n 100 文件名 tail 查看后n行 tail -n 3 file wc (word count )统计行数、单词数 Hello world Linux is great wc -l file #统计行数: 2 file wc -w file #统计单词数:5 file touch 新建文本文件,如touch /home/hello.py 将在home 文件夹下新建hello.py ls 列出所有文件,但默认只是显示出最基础的文件和文件夹,如果需要更详细的信息,则使用ls -la,这将列出包括隐藏文件在内的所有文件和文件夹,并且给出对应的权限、大小和日期等信息。 zy123@hcss-ecs-588d:~$ ls -la total 44 drwxr-xr-x 6 zy123 zy123 4096 Feb 26 08:53 . drwxr-xr-x 3 root root 4096 Feb 24 16:33 .. -rw------- 1 zy123 zy123 6317 Feb 25 19:41 .bash_history -rw-r--r-- 1 zy123 zy123 220 Feb 24 16:33 .bash_logout -rw-r--r-- 1 zy123 zy123 3526 Feb 24 16:33 .bashrc drwx------ 3 zy123 zy123 4096 Feb 24 16:35 .config drwxr-xr-x 3 zy123 zy123 4096 Feb 24 16:36 .local -rw-r--r-- 1 zy123 zy123 807 Feb 24 16:33 .profile drwxr-xr-x 5 zy123 zy123 4096 Feb 26 08:53 zbparse drwxr-xr-x 3 root root 4096 Feb 26 08:54 zbparse_output 权限与文件类型(第一列): 第一个字符表示文件类型: “d”表示目录(directory) “-”表示普通文件(regular file) “l”表示符号链接(symbolic link) 后续的9个字符分为3组,每组三个字符,分别代表所有者、所属组和其他用户的权限(读、写、执行)。 硬链接数(第二列): 表示指向该文件的硬链接数量。对于目录来说,这个数字通常会大于1,因为“.”和“..”也算在内。 所有者(第三列): 显示该文件或目录的拥有者用户名。 所属组(第四列): 显示该文件或目录所属的用户组。 文件大小(第五列): 以字节为单位显示文件的大小。对于目录,通常显示的是目录文件占用的磁盘空间(一般为4096字节)。 最后修改日期和时间(第六列): 显示文件最后一次修改的日期和时间(可能包含月、日和具体时间或年份)。 文件名或目录名(第七列): 显示文件或目录的名称。 cd 进入指定文件夹,如cd /home 将进入home目录。返回上层目录的命令是 cd .. ,返回刚才操作的目录的命令是 cd - mkdir 新建文件夹,如 mkdir /home/Python 将在home 文件夹下新建一个Python 文件夹。 mv 移动文件和文件夹,也可以用来重命名,如: mv /home/hello.py /home/helloworld.py 将上文的hello.py重命名为helloworld.py, mv /home/helloworld.py /home/Python/helloworld.py 将helloworld.py 由home文件夹移动到了次级的Python文件夹。 mv /home/hello.py . 将/home/hello.py 移动到当前目录下 cp 复制文件 cp /home/Python/hellowrold.py /home/Python/HelloWorld.py 将helloworld.py复制为HelloWolrd.py。注意:Linux系统严格区分大小写,helloworld.py和HelloWolrd.py是两个文件。 rm 删除,即江湖传说中 rm -rf ,r为递归,可以删除文件夹中的文件,f为强制删除。rm /home/Python/helloworld.py 可以删除刚才的helloworld.py 文件,而想删除包括Python 在内的所有文件,则是 rm -rf /home/Python 。 df -h 查看磁盘空间使用情况 grep 是用于在文件或标准输入中搜索符合条件的行的命令。 #test.txt Hello World hello linux Grep is useful HELLO GREP # 精确匹配大小写 grep "Hello" test.txt 输出:Hello World -i忽略大小写 -n显示行号 # 忽略大小写匹配 grep -i "hello" test.txt 输出: Hello World hello linux HELLO GREP awk 是一个功能强大的文本处理工具,它可以对文本文件进行分列处理、模式匹配和报告生成。它的语法类似一种简单的脚本语言。 awk 'pattern { action }' filename pattern:用于匹配文本的条件(可以省略,默认对所有行生效)。 action:在匹配的行上执行的操作。 $0:代表整行内容$1+ $2+ $3+ ...。 $1, $2, ...:代表各个列(默认分隔符是空白字符,可以通过 -F 参数指定其他分隔符)。 对于: A B C 1 Alice 25 Engineer 2 Bob 30 Designer awk '{print $1, $3}' filename #印指定列 输出: Alice Engineer Bob Designer sed sed -n '1000,$p' file 对于 filename这个文件,请只打印从第1000行开始一直到文件末尾的所有内容。$代表结尾,p是print打印。 管道 | 是将一个命令的输出直接传递给另一个命令作为输入的一种机制。 示例:将 grep 与 awk 联合使用:假设有一个日志文件 access.log,需要先用 grep 过滤出包含 "ERROR" 的行,再用 awk 提取时间字段: 127.0.0.1 27/Feb/2025:10:30:25 "GET /index.html HTTP/1.1" 200 1024 192.168.1.1 27/Feb/2025:10:31:45 "POST /login HTTP/1.1" 302 512 10.0.0.5 27/Feb/2025:10:32:10 "GET /error_page HTTP/1.1" 500 2048 ERROR grep 'ERROR' access.log | awk '{print $2}' 输出:27/Feb/2025:10:32:10 lsof"List Open Files"显示系统中当前打开的文件。 -i会显示所有正在使用网络连接的进程 lsof -i :80 #查看 80 端口上的进程,或者判断80端口是否被占用! netstat -ano | findstr :8080这是windows cmd下检查端口占用的命令 usermode 修改用户账户信息的命令 sudo usermod -aG docker zy123 #-aG一起用,添加zy123到group组 chmod 命令用于修改文件或目录的权限 数字方式:数字方式使用三个(或四个)数字来表示所有者、组用户和其他用户的权限。每个数字代表读 (4)、写 (2)、执行 (1) 权限的和。 chmod 644 filename #所有者:读 + 写 = 6 组用户:读 = 4 其他用户:读 = 4 符号方式 chmod [用户类别][操作符][权限] filename 用户类别: u:所有者(user) g:组用户(group) o:其他用户(others) a:所有用户(all),等同于 u+g+o 操作符: +:增加权限 -:去掉权限 =:直接设置权限 权限: r:读权限 w:写权限 x:执行权限 chmod u+x filename #为所有者增加执行权限 文本编辑器 nano:Debian 11自带了简便易用的nano文本编辑器 nano /etc/apt/sources.list #打开sources.list文件 Ctrl+O:保存修改 ->弹出询问-> Y则保存,N则不保存,ctrl+c 取消操作。 Ctrl+X:退出 vim 普通模式(Normal Mode): 打开 Vim 后默认进入普通模式。在该模式下,可以执行移动光标、删除、复制、粘贴等命令。 光标移动: 0:跳到当前行行首 $:跳到当前行行尾 gg: 将光标移到文件开头 文本操作: dd:删除(剪切)整行 yy:复制(拷贝)整行 p:在光标后粘贴(把剪切或复制的内容贴上) u:撤销上一步操作 Ctrl + r:重做上一步撤销的操作 插入模式(Insert Mode): 在普通模式下按 i、I、a、A 等键可进入插入模式,此时可以像普通编辑器那样输入文本。 按 ESC 键退出插入模式,返回普通模式。 可视模式(Visual Mode): 用于选中一段文本,自动进入可视模式。选中文本后可以进行复制、剪切等操作。 在可视模式下选中后按 d 删除 按 y 复制选中区域 命令行模式(Command-Line Mode): 在普通模式下,输入 : 进入命令行模式,可以执行保存、退出、查找等命令。 :w:保存当前文件 :q:退出 Vim(如果有未保存的修改会警告) :wq 或 :x:保存文件并退出 :q!:不保存强制退出 :set number:显示行号 :set paste:适用于代码或格式敏感的文本,确保粘贴操作不会破坏原有的布局和缩进。 :%d: 删除全文 抓包 sudo tcpdump -nn -i any port 1000 //查看请求端口1000的源 IP 地址 SSH 1. 生成密钥对 使用以下命令生成安全的 SSH 密钥对: ssh-keygen -t rsa -b 4096 -C "your_email@example.com" 生成的文件默认保存在用户主目录的 ~/.ssh/文件夹中: 私钥 (id_rsa):必须妥善保存在本地,严禁泄露。这是证明身份的核心凭证。 公钥 (id_rsa.pub):需要提供给服务端用于身份验证。 2. 核心概念:理解客户端与服务端 SSH 认证是双向的,关键在于分清每次连接中谁是客户端(主动发起连接的一方),谁是服务端(被动接受连接的一方)。 场景一:从服务器拉取 GitHub 代码 角色分配 客户端:你的 Linux 服务器(执行 git clone/push命令的机器) 服务端:GitHub 代码托管平台 认证流程 在客户端(你的服务器)生成 SSH 密钥对 将客户端的公钥内容添加到 GitHub 账户的 SSH Keys 设置中 当服务器执行 git clone git@github.com:...时: GitHub 会用存储的公钥发起挑战 你的服务器用本地私钥完成验证 本质:让你的服务器向 GitHub 证明其合法身份 场景二:通过 FinalShell 连接 Linux 服务器 角色分配 客户端:你的本地 Windows 电脑(运行 FinalShell 的机器) 服务端:目标 Linux 服务器 认证流程 在客户端(你的电脑)生成 SSH 密钥对 将客户端的公钥内容添加到服务端的 ~/.ssh/authorized_keys文件中 当 FinalShell 连接时: Linux 服务器用 authorized_keys中的公钥发起挑战 FinalShell 用本地私钥完成验证 本质:让你的电脑向 Linux 服务器证明你的用户身份 文件系统 在 Linux 系统中,整个文件系统从根目录 / 开始,下面简单介绍一些主要目录及其存放的文件类型: /bin 存放系统启动和运行时必需的用户二进制可执行文件,如常用的 shell 命令(例如 ls、cp、mv 等)。 /boot 包含启动加载器(如 GRUB)的配置文件和内核映像(kernel image),这些文件用于系统启动过程。 /dev 包含设备文件,这些文件代表系统中的各种硬件设备(例如硬盘、终端、USB 设备等),以及一些伪设备。 /etc 存放系统范围内的配置文件,例如网络配置、用户账户信息、服务配置等。这些文件通常由管理员维护。 /home 为普通用户提供的家目录,每个用户在这里有一个独立的子目录,存放个人文件和配置。 /lib 和 /lib64 存放系统和应用程序所需的共享库文件,这些库支持 /bin、/sbin 及其他程序的运行。 /media 通常用于挂载移动介质,如光盘、U 盘或其他可移动存储设备。 /mnt 提供一个临时挂载点,一般供系统管理员在需要手动挂载文件系统时使用。 /opt 用于安装附加的应用程序软件包,通常是第三方提供的独立软件,不与系统核心软件混合。 /proc 这是一个虚拟文件系统,提供内核和进程信息,例如系统资源使用情况、硬件信息、内核参数等。这里的文件不占用实际磁盘空间。 /root 系统管理员(root 用户)的家目录,与普通用户的 /home 分开存放。 /run 存储系统启动后运行时产生的临时数据,比如 PID 文件、锁文件等,系统重启后会清空该目录。 /sbin 存放系统管理和维护所需的二进制文件(系统级命令),例如网络配置、磁盘管理工具等,这些通常只由 root 用户使用。 /srv 用于存放由系统提供的服务数据,如 FTP、HTTP 服务的数据目录等。 /tmp 用于存放临时文件,许多应用程序在运行时会将临时数据写入这里,系统重启后通常会清空该目录。 /usr 存放大量用户应用程序和共享资源,其子目录包括: /usr/bin:大部分用户命令和应用程序。 /usr/sbin:非基本系统维护工具,主要供系统管理员使用。 /usr/lib:程序库文件。 /usr/share:共享数据,如文档、图标、配置样本等。 /var 存放经常变化的数据,如日志文件、缓存、邮件、打印队列和临时应用数据等。 Bash #!/bin/bash # 定义变量,注意等号两边不能有空格 name="World" # 如果脚本传入了参数,则使用第一个参数覆盖默认值 if [ $# -ge 1 ]; then # $# 表示传入脚本的参数个数 name=$1 # $1 表示第一个参数。 fi # 输出问候语 echo "Hello, $name!" #变量引用时要用 $ 符号,如 $name。 # 循环示例:遍历1到5的数字 for i in {1..5}; do echo "当前数字:$i" done # 定义一个函数,函数名为greet greet() { echo "函数内问候: Hello, $1!" } # 调用函数,并传入变量name作为参数 greet $name 如何运行? 赋予可执行权限 chmod +x hello_world.sh 执行 ./hello_world.sh 或者 ./hello_world.sh Alice #传参 在 Linux 系统中,默认情况下当前目录(.)并不包含在 PATH 环境变量中。这意味着,如果你在终端中直接输入脚本名(例如 hello_world.sh),系统不会在当前目录下查找这个脚本,而是只在 PATH 中指定的目录中查找可执行程序。使用 ./hello_world.sh 表示“在当前目录下执行 hello_world.sh”,从而告诉系统正确的路径。 如何设置定时任务? sudo crontab -e #在里面添加: 10 0 * * * /path/toyour/xx.sh #让gpt写 反向代理神器——Nginx Proxy Manager 【Docker系列】一个反向代理神器——Nginx Proxy Manager-我不是咕咕鸽 概念 正向代理是代理客户端的行为,即代理服务器代表客户端向目标服务器发出请求。客户端将自己的请求先发送给代理服务器,由代理服务器转发给真正的目标服务器,然后再将返回结果传递给客户端。 特点: 保护访问者(客户端)的信息:目标服务器只会看到代理服务器的请求,无法直接获知真正发起请求的客户端是谁。 应用场景:当客户端出于隐私、访问控制或跨越网络限制的目的,需要隐藏自己的真实IP或身份时,会使用正向代理。 反向代理是代理服务器代表目标服务器接收客户端请求,并将请求转发给内部的真实服务器,然后将结果返回给客户端。客户端只与代理服务器通信,而不知道背后实际处理请求的服务器。 特点: 保护服务器端的信息:客户端看不到真正的服务器细节,只知道代理服务器。这样可以隐藏真实服务器的 IP 和其他内部结构信息,从而增强安全性和负载均衡等功能。 应用场景:在大型网站或应用中,为了防止恶意攻击或实现负载均衡,通常会在真实服务器前部署一个反向代理服务器。 docker 部署 version: '3' services: app: image: 'jc21/nginx-proxy-manager:latest' restart: unless-stopped ports: - '80:80' # 保持默认即可,不建议修改左侧的80 - '81:81' # 冒号左边可以改成自己服务器未被占用的端口 - '443:443' # 保持默认即可,不建议修改左侧的443 volumes: - ./data:/data # 冒号左边可以改路径,现在是表示把数据存放在在当前文件夹下的 data 文件夹中 - ./letsencrypt:/etc/letsencrypt # 冒号左边可以改路径,现在是表示把数据存放在在当前文件夹下的 letsencrypt 文件夹中 NPM后台管理网站运行在81号端口,NPM服务本身监听80(http)和443(https)端口 工作原理 用户访问网站(80/443端口) 当用户访问 https://blog.test.com 时,请求到达服务器的443端口。 Nginx根据域名匹配代理规则(由NPM配置),将请求转发到后端服务(如 192.168.1.100:8080)。 管理员访问后台(81端口) 管理员通过 http://服务器IP:81 访问NPM管理界面,配置代理规则。 配置完成后,NPM会自动生成Nginx配置文件并重启Nginx服务,使新规则生效。 两种方法实现SSL安全连接 1. 开启橙云+Cloudflare Origin CA:网站SSL证书自动续期又又又失败了?试试CloudFlare的免费证书,15年有效期!-我不是咕咕鸽 cloudflare解析DNS,开启橙云 Cloudflare Full (strict)模式(灵活模式下无需以下步骤) 在 Nginx Proxy Manager(NPM)添加 Cloudflare Origin CA 配置 Proxy Host 使其使用 选择刚刚添加的 Cloudflare Origin CA 证书 选择 Force SSL(强制 HTTPS) 启用 HTTP/2 支持 Cloudflare Origin CA作用:实现cloudflare与源服务器之间的流量加密 2.通配符SSL证书:【Docker系列】反向代理神器NginxProxyManager——通配符SSL证书申请-我不是咕咕鸽 更推荐第二种!!!目前正在使用,但是3个月续签一次证书! 浏览器 → (HTTPS) → NPM → (HTTP 或 HTTPS) → Gitea 这就是反向代理常见的工作流程。 默认经常是 NPM 做 SSL 终止(内网用 HTTP 转发给 Gitea)。如果你想内外全程加密,就要让 NPM -> Gitea 这段也走 HTTPS,并在 Gitea 上正确配置证书。 正向代理(用于拉取镜像) 下载Clash客户端:Release Clash-Premium · DustinWin/proxy-tools 或者Index of /Linux/centOS/ 我是windows上下载clashpremium-release-linux-amd64.tar.gz 然后FTP上传到linux服务器上。 下载配置文件config.yaml:每个人独一无二的 wget -O /home/zy123/VPN/config.yaml "https://illo1.no-mad-world.club/link/2zXAEzExPjAi6xij?clash=3" 类似这样: port: 7890 socks-port: 7891 allow-lan: false mode: Rule //Global log-level: info external-controller: 0.0.0.0:9090 unified-delay: true hosts: time.facebook.com: 17.253.84.125 time.android.com: 17.253.84.125 dns: enable: true use-hosts: true nameserver: - 119.29.29.29 - 223.5.5.5 - 223.6.6.6 - tcp://223.5.5.5 - tcp://223.6.6.6 - tls://dns.google:853 - tls://8.8.8.8:853 - tls://8.8.4.4:853 - tls://dns.alidns.com - tls://223.5.5.5 - tls://223.6.6.6 - tls://dot.pub - tls://1.12.12.12 - tls://120.53.53.53 - https://dns.google/dns-query - https://8.8.8.8/dns-query - https://8.8.4.4/dns-query - https://dns.alidns.com/dns-query - https://223.5.5.5/dns-query - https://223.6.6.6/dns-query - https://doh.pub/dns-query - https://1.12.12.12/dns-query - https://120.53.53.53/dns-query default-nameserver: - 119.29.29.29 - 223.5.5.5 - 223.6.6.6 - tcp://119.29.29.29 - tcp://223.5.5.5 - tcp://223.6.6.6 proxies: - {name: 🇭🇰 香港Y01, server: qvhh1-g03.hk01-ae5.entry.v50307shvkaa.art, port: 19273, type: ss, cipher: aes-256-gcm, password: 6e4124c4-456e-36a3-b144-c0e1a618d04c, udp: true} 注意,魔戒vpn给的是一个订阅地址!!!还需要解码 简便方法:windows上将订阅链接导入,自动解析成yaml配置文件,然后直接把该文件传到服务器上! 启动Clash ./CrashCore -d . & //后台启动 为Clash创建服务 1.创建 systemd 服务文件 sudo vim /etc/systemd/system/clash.service 2.在文件中添加以下内容: [Unit] Description=Clash Proxy Service After=network.target [Service] ExecStart=/home/zy123/VPN/CrashCore -d /home/zy123/VPN WorkingDirectory=/home/zy123/VPN Restart=always User=zy123 Group=zy123 [Install] WantedBy=multi-user.target 这段配置将 Clash 配置为: 在网络服务启动后运行。 在启动时自动进入后台,执行 CrashCore 服务。 如果服务意外停止,它将自动重启。 以 zy123 用户身份运行 Clash。 启动服务: sudo systemctl start clash 停止服务: sudo systemctl stop clash 查看服务状态: sudo systemctl status clash 配置YACD YACD 是一个基于 Clash 的 Web 管理面板,用于管理您的 Clash 配置、查看流量和节点信息等。 直接用现成的:https://yacd.haishan.me/ 服务器上部署:目前是npm手动构建安装启动的。 下载yacd git clone https://github.com/haishanh/yacd.git 安装npm 构建yacd cd ~/VPN/yacd pnpm install pnpm build 启动yacd nohup pnpm serve --host 0.0.0.0 & //如果不是0.0.0.0 不能在windows上打开 停止进程 ps aux | grep pnpm kill xxx 通过http://124.71.159.195:4173/ 访问yacd控制面板。手动添加crash服务所在的ip:端口。 如果连不上:yacd面板和crash都是http协议就行了。 连接测试 直连: curl -v https://www.google.com 使用代理:curl -x http://127.0.0.1:7890 https://www.google.com File Browser 文件分享 https://github.com/filebrowser/filebrowser Docker 部署 File Browser 文件管理系统_filebrowser docker-CSDN博客 1.创建数据目录 mkdir -p /data/filebrowser/{srv,config,db} 2.目录授权 chmod -R 777 /data/filebrowser/ 3.编辑 docker-compose.yaml 文件 version: '3' services: filebrowser: image: filebrowser/filebrowser:s6 container_name: filebrowser restart: always ports: - "2000:80" # 将容器的80端口映射到宿主机2000端口 volumes: - /data/filebrowser/srv:/srv #保存用户上传的文件 - /data/filebrowser/config:/config # 配置文件存储路径 - /data/filebrowser/db:/database #数据库存储路径 调用API实现文件上传与下载 登录: # 登录 → 获取 JWT token(原始字符串) curl -X POST "yourdomain/api/login" \ -H "Content-Type: application/json" \ -d '{ "username": "admin", "password": "123456" }' 响应: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" //jwt令牌 上传: # 先把 token 保存到环境变量(假设你已经执行过 /api/login 并拿到了 JWT) export TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…" # 定义要上传的本地文件和目标名称 FILE_PATH="/path/to/local/photo.jpg" OBJECT_NAME="photo.jpg" # 对远程路径做 URL 编码(保留斜杠) REMOTE_PATH="store/${OBJECT_NAME}" ENCODED_PATH=$(printf "%s" "${REMOTE_PATH}" \ | jq -sRr @uri \ | sed 's/%2F/\//g') # 发起上传请求(raw body 模式) curl -v -X POST "https://yourdomain/api/resources/${ENCODED_PATH}?override=true" \ -H "X-Auth: ${TOKEN}" \ -H "Content-Type: image/jpeg" \ # 根据文件后缀改成 image/png 等 --data-binary "@${FILE_PATH}" 获取分享链接url: # 假设已经执行过 /api/login 并把 JWT 保存在环境变量 TOKEN # 同样复用之前算好的 ENCODED_PATH 和 REMOTE_PATH # 调用分享接口(注意:POST,body 为空 JSON "{}") curl -s -X POST "https://yourdomain/api/share/${ENCODED_PATH}" \ -H "X-Auth: ${TOKEN}" \ -H "Cookie: auth=${TOKEN}" \ -H "Content-Type: text/plain;charset=UTF-8" \ -d '{}' \ | jq -r '.hash' \ | xargs -I{} printf "https://yourdomain/api/public/dl/%s/%s\n" {} "${REMOTE_PATH}" Gitea Gitea Docker 安装与使用详解:轻量级自托管 Git 服务教程-CSDN博客 version: "3" services: gitea: image: gitea/gitea:latest container_name: gitea environment: - USER_UID=1000 - USER_GID=1000 restart: always ports: - "3000:3000" # 将宿主机的3000端口映射到容器的3000端口 volumes: - /data/gitea:/data # 持久化存储Gitea数据(包括仓库、配置、日志等) EasyImage 【好玩儿的Docker项目】10分钟搭建一个简单图床——Easyimage-我不是咕咕鸽 github地址:icret/EasyImages2.0: 简单图床 - 一款功能强大无数据库的图床 2.0版 sudo -i # 切换到root用户 apt update -y # 升级packages apt install wget curl sudo vim git # Debian系统比较干净,安装常用的软件 version: '3.3' services: easyimage: image: ddsderek/easyimage:latest container_name: easyimage ports: - '1000:80' environment: - TZ=Asia/Shanghai - PUID=1000 - PGID=1000 volumes: - '/root/data/docker_data/easyimage/config:/app/web/config' - '/root/data/docker_data/easyimage/i:/app/web/i' restart: unless-stopped 网页打开显示bug: cd /data/easyimage/config/config.php 这里添加上https 网站域名 图片域名设置可以改变图片的url:IP或域名 picgo安装: Releases · Molunerfinn/PicGo 1.右下角小窗打开 2.插件设置,搜索web-uploader 1.1.1 (自定义web图床) 旧版有搜索不出来的情况!建议直接安装最新版! 3.配置如下,API地址从easyimage-设置-API设置中获取 typora设置 左上角文件-偏好设置-图像-插入图片时{ 上传图片-picgo服务器-填写picgo安装路径 } ps:还可以选择上传到./assets,每个md文件独立 或者上传到指定路径如/image,多个md文件共享 py脚本1:将所有md文件中的图片路径改为本地,统一保存到本地output文件夹中 py脚本2:将每个md文件及其所需图片单独保存,保存到本地,但每个md文件有自己独立的assets文件夹 py脚本3:将本地图片上传到easyimage图床并将链接返回替换md文件中的本地路径 Typecho 【好玩儿的Docker项目】10分钟搭建一个Typecho博客|太破口!念念不忘,必有回响!-我不是咕咕鸽 typecho:https://github.com/typecho/typecho/ 注意:nginx一定要对typecho目录有操作权限! sudo chmod 755 -R ./typecho services: nginx: image: nginx ports: - "4000:80" # 左边可以改成任意没使用的端口 restart: always environment: - TZ=Asia/Shanghai volumes: - ./typecho:/var/www/html - ./nginx:/etc/nginx/conf.d - ./logs:/var/log/nginx depends_on: - php networks: - web php: build: php restart: always expose: - "9000" # 不暴露公网,故没有写9000:9000 volumes: - ./typecho:/var/www/html environment: - TZ=Asia/Shanghai depends_on: - mysql networks: - web pyapp: build: ./markdown_operation # Dockerfile所在的目录 restart: "no" networks: - web env_file: - .env depends_on: - mysql mysql: image: mysql:5.7 restart: always environment: - TZ=Asia/Shanghai expose: - "3306" # 不暴露公网,故没有写3306:3306 volumes: - ./mysql/data:/var/lib/mysql - ./mysql/logs:/var/log/mysql - ./mysql/conf:/etc/mysql/conf.d env_file: - mysql.env networks: - web networks: web: 卸载: sudo -i # 切换到root cd /root/data/docker_data/typecho # 进入docker-compose所在的文件夹 docker-compose down # 停止容器,此时不会删除映射到本地的数据 cd ~ rm -rf /root/data/docker_data/typecho # 完全删除映射到本地的数据 主题 Joe主题:https://github.com/HaoOuBa/Joe Joe再续前缘主题 - 搭建本站同款网站 - 易航博客 自定义文章详情页的上方信息(如更新日期/文章字数第): /typecho/usr/themes/Joe/functions.php中定义art_count,统计字数(粗略)。 原始 Markdown → [1] 删除代码块/行内代码/图片/链接标记/标题列表标记/强调符号 → [2] strip_tags() + html_entity_decode() → [3] 正则保留 “文字+数字+标点”,去除其它 → 结果用 mb_strlen() 得到最终字数 typecho/usr/themes/Joe/module/single/batten.php <?php if (!defined('__TYPECHO_ROOT_DIR__')) { http_response_code(404); exit; } ?> <h1 class="joe_detail__title"><?php $this->title() ?></h1> <div class="joe_detail__count"> <div class="joe_detail__count-information"> <a href="<?php $this->author->permalink(); ?>"> <img width="38" height="38" class="avatar lazyload" src="<?php joe\getAvatarLazyload(); ?>" data-src="<?php joe\getAvatarByMail($this->author->mail) ?>" alt="<?php $this->author(); ?>" /> </a> <div class="meta ml10"> <div class="author"> <a class="link" href="<?php $this->author->permalink(); ?>" title="<?php $this->author(); ?>"><?php $this->author(); ?></a> </div> <div class="item"> <span class="text"> <?php echo $this->date('Y-m-d'); ?> / <?php $this->commentsNum('%d'); ?> 评论 / <?php echo joe\getAgree($this); ?> 点赞 / <?php echo joe\getViews($this); ?> 阅读 / <?php echo art_count($this->cid); ?> 字 </span> </div> </div> </div> </div> <div class="relative" style="padding-right: 40px;"> <i class="line-form-line"></i> <!-- 新增最近修改日期显示 --> <div style="font-size: 1.0em; position: absolute; right: 20px; top: 50%; transform: translateY(-50%);"> 最后更新于 <?php echo date('m-d', $this->modified); ?> </div> <div class="flex ac single-metabox abs-right"> <div class="post-metas"> <!-- 原图标及其他冗余信息已删除 --> </div> <div class="clearfix ml6"> <!-- 编辑文章/页面链接已删除 --> </div> </div> </div> 修改代码块背景色: typecho/usr/themes/Joe/assets/css/joe.global.css .joe_detail__article code:not([class]) { border-radius: var(--radius-inner, 4px); /* 可以设置一个默认值 */ background: #f5f5f5; /* 稍微偏灰的背景色 */ color: #000000; /* 黑色字体 */ padding: 2px 6px; /* 内边距可以适当增大 */ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; word-break: break-word; font-weight: normal; -webkit-text-size-adjust: 100%; -webkit-font-smoothing: antialiased; white-space: pre-wrap; /* 保持代码换行 */ font-size: 0.875em; margin-inline-start: 0.25em; margin-inline-end: 0.25em; } 大坑: 会显示为勾选框,无法正常进行latex公式解析,因为typecho/usr/themes/Joe/public/short.php中设置了短代码替换,在文章输出前对 $content 中的特定标记或短代码进行搜索和替换,从而实现一系列自定义功能。现已全部注释。 typecho/usr/themes/Joe/assets/js/joe.single.js原版: 显示弹窗,点叉后消失 { document.querySelector('.joe_detail__article').addEventListener('copy', () => { autolog.log(`本文版权属于 ${Joe.options.title} 转载请标明出处!`, 'warn', false); }); } 显示5秒后消失: document.querySelector('.joe_detail__article').addEventListener('copy', () => { // 显示 autolog 消息 autolog.log(`本文版权属于 ${Joe.options.title} 转载请标明出处!`, 'warn', false); // 5 秒后删除该消息 setTimeout(() => { const warnElem = document.querySelector('.autolog-warn'); if (warnElem) { warnElem.remove(); // 或者使用 warnElem.style.display = 'none'; } }, 5000); }); markdown编辑与解析 确保代码块```后面紧跟着语言,如```java,否则无法正确显示。 markdown编辑器插件:https://xiamp.net/archives/aaeditor-is-another-typecho-editor-plugin.html '开启公式解析!' markdown解析器插件:mrgeneralgoo/typecho-markdown: A markdown parse plugin for typecho. 关闭公式解析,仅开启代码解析! slug为页面缩略名,在新增文章时可以传入,默认是index数字。 qBittorrent 【好玩的Docker项目】10分钟搭建你专属的下载神器——qbittorrent-我不是咕咕鸽 docker pull linuxserver/qbittorrent cd ~ mkdir /root/data/docker_data/qBittorrent #创建qbitorrent数据文件夹 cd /root/data/docker_data/qBittorrent mkdir config downloads #创建配置文件目录与下载目录 nano docker-compose.yml #创建并编辑文件 services: qbittorrent: image: linuxserver/qbittorrent container_name: qbittorrent environment: - PUID=1000 - PGID=1000 - TZ=Asia/Shanghai # 你的时区 - UMASK_SET=022 - WEBUI_PORT=8081 # 将此处修改成你欲使用的 WEB 管理平台端口 volumes: - ./config:/config # 绝对路径请修改为自己的config文件夹 - ./downloads:/downloads # 绝对路径请修改为自己的downloads文件夹 ports: # 要使用的映射下载端口与内部下载端口,可保持默认,安装完成后在管理页面仍然可以改成其他端口。 - 6881:6881 - 6881:6881/udp # 此处WEB UI 目标端口与内部端口务必保证相同,见问题1 - 8081:8081 restart: unless-stopped 有个bug!qBittorrent 登录遇到 unauthorized的解决方法: 1、先停止容器docker compose down 2、进入配置文件夹config,编辑qBittorrent.conf在文末加上: WebUI\HostHeaderValidation=false WebUI\CSRFProtection=false 3.如果还是进不去,在地址后端添加'/' 内网穿透 使用服务提供商 网址:https://natapp.cn 1.隧道查看 2.隧道配置 配置映射关系: 3.客户端下载与配置 https://natapp.cn/#download ,参考官方文档,配置本地token,启动本地客户端。 自己搭建FRP 数据流转流程 外部请求到达 frp-server 你在 frps.ini(服务端配置)里为某个 proxy 分配了一个 remote_port(或 custom_domains)。 当外部用户(浏览器、移动端、其他服务)访问 http://your.frps.ip:remote_port/... 时,流量首先打到你部署在公网的 frp-server 上。 frp-server 转发到 frp-client frp-server 维护着一个与每个 frp-client 的长连接(control connection)。 收到外部连接后,frp-server 会基于这个 control 通道告诉对应的 frp-client: “有一个新连接,请你去拿 proxy(name) 对应的后端服务数据。” frp-server 不自己去连 Java 后端,它只是做信令和数据的“管道”管理。 frp-client 建立到本地 Java 服务的连接 frp-client 收到信令后,内部根据 proxies 配置: [[proxies]] name = "my-java-app" type = "tcp" local_ip = "127.0.0.1" local_port = 8080 remote_port= 18080 它会在容器或宿主机内部打开一个新的 TCP 连接,指向 127.0.0.1:8080(即你的 Java 服务) frp-server frps.toml: # https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml [common] # 监听端口 bind_port = 7000 # 面板端口 dashboard_port = 7500 # 登录面板的账号密码(修改成自己的) dashboard_user = admin dashboard_pwd = admin # token = docker-compose: version: '3.9' services: frps: image: fatedier/frps:v0.60.0 hostname: frps container_name: frps volumes: - "./config/frps.toml:/frps.toml" command: - "-c" - "/frps.toml" network_mode: "host" frp-client frpc.toml: # 服务端地址 https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml serverAddr = "124.71.159.195" # 服务端配置的bindPort serverPort = 7000 # token = [[proxies]] # 代理应用名称,根据自己需要进行配置 name = "smile-dev-tech-01" # 代理类型 有tcp\udp\stcp\p2p type = "tcp" # 客户端代理应用IP localIP = "host.docker.internal" # 客户端代理应用端口 localPort = 8234 # 服务端反向代理端口;提供给外部访问 remotePort = 8234 [[proxies]] # 代理应用名称,根据自己需要进行配置 name = "smile-dev-tech-02" # 代理类型 有tcp\udp\stcp\p2p type = "tcp" # 客户端代理应用IP localIP = "host.docker.internal" # 客户端代理应用端口 localPort = 9001 # 服务端反向代理端口;提供给外部访问 remotePort = 9001 docker-compose: # 命令执行 docker-compose -f docker-compose.yml up -d version: '3.9' services: frpc: image: fatedier/frpc:v0.60.0 hostname: frpc container_name: frpc volumes: - "./config/frpc.toml:/frpc.toml" command: - "-c" - "/frpc.toml" network_mode: "host" frp-server必须部署在有公网ip的服务器,frp-client客户端有两种部署方式: 1.docker部署,如上 2.下载windows客户端https://github.com/fatedier/frp/releases/tag/v0.60.0 **注意:**如果java后端和client都部署在docker同一网络中,frpc.toml 中 localIP = "localhost" 如果client在docker容器,java在idea中启动,那么 localIP = "host.docker.internal" 如果client在windows下启动,java在idea中启动, localIP = "localhost" 总之,关键是让client和java互通;client和server互通比较容易!!! 公网ip:7500 可以查看面板。
杂项
zy123
3月21日
0
6
0
1
2
3
下一页