-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.json
1 lines (1 loc) · 123 KB
/
content.json
1
{"meta":{"title":"chuchu-z","subtitle":"","description":"借君三十年,繁花万里好江山","author":"chuchu-z","url":"http://chuchu-z.com","root":"/"},"posts":[{"title":"Supervisor 管理 Docker 容器内进程问题","slug":"supervisor-docker-container-process-issues","date":"2024-07-24T09:49:33.000Z","updated":"2024-12-31T06:57:56.021Z","comments":true,"path":"posts/supervisor-docker-container-process-issues/","link":"","permalink":"http://chuchu-z.com/posts/supervisor-docker-container-process-issues/","excerpt":"问题描述:在测试环境中发现,宿主机的 Supervisor 进程管理工具无法有效管理 Docker 容器内由 docker exec php7 命令创建的 PHP 进程。这导致 Supervisor 对 Docker 容器内的 PHP 进程无法进行有效的控制和重启 预期行为:宿主机的 Supervisor 应能够控制 Docker 容器内由 docker exec php7 命令创建的 PHP 进程,包括启动、停止和重启","text":"问题描述:在测试环境中发现,宿主机的 Supervisor 进程管理工具无法有效管理 Docker 容器内由 docker exec php7 命令创建的 PHP 进程。这导致 Supervisor 对 Docker 容器内的 PHP 进程无法进行有效的控制和重启 预期行为:宿主机的 Supervisor 应能够控制 Docker 容器内由 docker exec php7 命令创建的 PHP 进程,包括启动、停止和重启 supervisor 配置如下: [program:laikeduo_test_rabbitmq_processor] command=docker exec php7 php /var/www/laikeduo_test/artisan rabbitmq:process-messages directory=/var/www/laikeduo_test autostart=true autorestart=true stopasgroup=true killasgroup=true stderr_logfile=/var/www/laikeduo_test/storage/logs/laikeduo_test_rabbitmq_processor.err.log stdout_logfile=/var/www/laikeduo_test/storage/logs/laikeduo_test_rabbitmq_processor.out.log 现象与分析现象:关闭或重启Supervisor, 只会对本身的docker exec php7命令生效, 容器内部已经启动的进程不受影响 [root@iZwz995otwrhk15lyjqnpkZ laikeduo_test]# ps -aux | grep artisan root 19379 0.0 0.9 1307524 16776 ? Sl 16:47 0:00 docker exec php7 php /var/www/laikeduo_test/artisan queue:work root 19380 0.1 0.9 1307780 16584 ? Sl 16:47 0:00 docker exec php7 php /var/www/laikeduo_test/artisan rabbitmq:process-messages www 19407 0.6 1.7 92228 30780 ? Ss 16:47 0:00 php /var/www/laikeduo_test/artisan queue:work www 19416 0.7 1.6 92228 30200 ? Ss 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages www 19433 0.0 1.3 92228 23532 ? S 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages www 19434 0.0 1.3 92228 23528 ? S 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages www 19435 0.0 1.3 92228 23524 ? S 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages www 19436 0.0 1.3 92228 23532 ? S 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages root 19441 0.0 0.0 112816 980 pts/0 R+ 16:47 0:00 grep --color=auto artisan [root@iZwz995otwrhk15lyjqnpkZ laikeduo_test]# systemctl stop supervisord [root@iZwz995otwrhk15lyjqnpkZ laikeduo_test]# ps -aux | grep artisan www 19407 0.3 1.7 92228 30780 ? Ss 16:47 0:00 php /var/www/laikeduo_test/artisan queue:work www 19416 0.3 1.6 92228 30200 ? Ss 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages www 19433 0.0 1.3 92228 23532 ? S 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages www 19434 0.0 1.3 92228 23528 ? S 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages www 19435 0.0 1.3 92228 23524 ? S 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages www 19436 0.0 1.3 92228 23532 ? S 16:47 0:00 php /var/www/laikeduo_test/artisan rabbitmq:process-messages root 19451 0.0 0.0 112812 980 pts/0 R+ 16:47 0:00 grep --color=auto artisan [root@iZwz995otwrhk15lyjqnpkZ laikeduo_test]# ps -aux | grep 'artisan' | grep -v grep | awk '{print $2}' | xargs kill -9 [root@iZwz995otwrhk15lyjqnpkZ laikeduo_test]# ps -aux | grep artisan root 19493 0.0 0.0 112812 980 pts/0 S+ 16:48 0:00 grep --color=auto artisan 分析: docker exec 命令在宿主机上启动,并不能直接控制容器内的进程。Supervisor 对 docker exec 命令的控制只限于启动和停止 docker exec 进程,而不会直接影响容器内部的进程 Supervisor 对宿主机上的 docker exec 命令进行管理,但不具备对容器内 PHP 进程的控制能力,因此无法有效管理已经在容器内启动的 PHP 进程 解决方案如果容器内部已经存在过多相关的进程无法删除, 只能指定删除包含artisan关键词的所有进程或者直接关闭再启动php7容器 方法 1:直接 kill 掉包含 artisan 关键词的进程 ps -aux | grep 'artisan' | grep -v grep | awk '{print $2}' | xargs kill -9 方法 2:先关闭再启动 PHP 容器, 经测试, docker-compose restart php7 可能无效 docker-compose stop php7 docker-compose start php7","categories":[{"name":"Linux","slug":"linux","permalink":"http://chuchu-z.com/categories/linux/"},{"name":"Docker","slug":"linux/docker","permalink":"http://chuchu-z.com/categories/linux/docker/"}],"tags":[]},{"title":"Dockerfile 优化历程","slug":"dockerfile-optimization-story","date":"2024-02-28T01:53:59.000Z","updated":"2024-12-31T06:57:56.013Z","comments":true,"path":"posts/dockerfile-optimization-story/","link":"","permalink":"http://chuchu-z.com/posts/dockerfile-optimization-story/","excerpt":"使用dockerfile构建一个Python环境的容器, 但是构建出来的镜像太大了, 可以优化一下。","text":"使用dockerfile构建一个Python环境的容器, 但是构建出来的镜像太大了, 可以优化一下。 原DockerfileFROM python:3.12 WORKDIR /app COPY . /app # pip 安装 Python 依赖后, 使用 sed 注释 /usr/local/lib/python3.12/site-packages/django/db/backends/base/base.py 的 225行, 避免检查mysql版本 RUN apt-get update && \\ apt-get install -y sed && \\ pip install --no-cache-dir -r requirements.txt && \\ sed -i '225s/^/#/' /usr/local/lib/python3.12/site-packages/django/db/backends/base/base.py EXPOSE 9527 CMD [\"python\", \"manage.py\", \"runserver\", \"0.0.0.0:9527\"] 镜像大小: 1.35GB 优化1-多阶段构建# 阶段1 FROM python:3.12 AS builder WORKDIR /app COPY . /app # 创建并激活虚拟环境 RUN python -m venv /venv && \\ # 使用 pip 安装 Python 依赖 /venv/bin/pip install --no-cache-dir -r requirements.txt && \\ # 更新 apt-get apt-get update && \\ # 安装 sed apt-get install -y sed && \\ # 使用 sed 注释 /venv/lib/python3.12/site-packages/django/db/backends/base/base.py 的 225行,避免检查mysql版本 sed -i '225s/^/#/' /venv/lib/python3.12/site-packages/django/db/backends/base/base.py # 阶段2 FROM python:3.12 WORKDIR /app COPY --from=builder /venv /venv COPY --from=builder /app /app # 设置环境变量 ENV PATH=\"/venv/bin:$PATH\" EXPOSE 9527 CMD [\"python\", \"manage.py\", \"runserver\", \"0.0.0.0:9527\"] 镜像大小: 1.17GB 优化2-使用Alpine基础镜像使用Alpine Linux 时, 由于缺少完整的扩展包依赖, 然后又遇到了安装 mysqlclient 时错误的问题, 折腾好久, 功夫不负有心人, 在 Stack Overflow 找到了一个可参考的, 然后稍作修改 FROM python:3.12-alpine WORKDIR /app COPY requirements.txt . # 更新 Alpine Linux 软件包索引 RUN apk update && \\ # 安装构建依赖和 MariaDB 开发依赖 apk add --no-cache --virtual build-deps gcc musl-dev libffi-dev pkgconf mariadb-dev && \\ # 安装 mariadb-connector-c-dev 依赖 apk add --no-cache mariadb-connector-c-dev && \\ # 使用 pip 安装 Python 依赖 pip install --no-cache-dir -r requirements.txt && \\ # 使用 sed 注释 /usr/local/lib/python3.12/site-packages/django/db/backends/base/base.py 的 225行,避免检查mysql版本 sed -i '225s/^/#/' /usr/local/lib/python3.12/site-packages/django/db/backends/base/base.py && \\ # 删除构建依赖,减小镜像体积 apk del build-deps COPY . . EXPOSE 9527 CMD [\"python\", \"manage.py\", \"runserver\", \"0.0.0.0:9527\"] 此时再看镜像大小, 已经来到了210MB 优化3-使用Alpine基础镜像+多阶段构建虽然210MB已经达到我的预期标准了, 但是我还想试试alpine+多阶段构建后有多大, 但是在分阶段这里总是遇到一些问题, 多次尝试还是未能攻克, 但是这个想法还是保留下来, 后期对docker构建流程更为精进再回来重新尝试。","categories":[{"name":"Docker","slug":"docker","permalink":"http://chuchu-z.com/categories/docker/"}],"tags":[]},{"title":"Dockerfile中的COPY与volume挂载冲突问题","slug":"dockerfile-COPY-vs-Volume-Conflicts","date":"2024-02-21T02:52:28.000Z","updated":"2024-12-31T06:57:56.013Z","comments":true,"path":"posts/dockerfile-COPY-vs-Volume-Conflicts/","link":"","permalink":"http://chuchu-z.com/posts/dockerfile-COPY-vs-Volume-Conflicts/","excerpt":"闲来无事, 想起之前本地构建博客想看看效果时, 老是出现文章内容丢失的问题, 后来构建时尝试加上--no-cache可以解决该问题, 现在又想折腾一下容器静态文件挂载到宿主机","text":"闲来无事, 想起之前本地构建博客想看看效果时, 老是出现文章内容丢失的问题, 后来构建时尝试加上--no-cache可以解决该问题, 现在又想折腾一下容器静态文件挂载到宿主机 docker-compose build --no-cache && docker-compose up -d DockerfileFROM node:14 AS builder WORKDIR /app COPY . . RUN npm install --no-fund && npx hexo clean && npx hexo generate FROM nginx:alpine WORKDIR /usr/share/nginx/html COPY --from=builder /app/public /usr/share/nginx/html EXPOSE 8080 docker-compose.ymlversion: '3' services: hexo: build: context: . dockerfile: Dockerfile image: chuchuzz426/blog-hexo:1.0 ports: - \"8080:80\" volume: - ./public:/usr/share/nginx/html # 挂载会把Dockerfile中的COPY覆盖 想法我想把 COPY --from=builder /app/public /usr/share/nginx/html 这一步的/usr/share/nginx/html目录下的静态资源挂载到宿主机 当时脑回路有点迷糊, 想着这样能方便查看或者在宿主机也能刷新静态资源? 但是犯傻忘了每次新的静态资源也是要先通过容器才能生成的😓, 还折腾了起来 最后挂载没成功, 倒是遇到了个COPY与挂载的冲突问题。 问题 如果已经在 Dockerfile 中使用COPY --from=builder /app/public /usr/share/nginx/html将一阶段的静态文件复制到Nginx阶段,然后在运行容器时再试图使用-v或--volume在宿主机上把./public目录挂载到容器的/usr/share/nginx/html,会导致挂载冲突, 具体表现方式为, COPY的文件被宿主机上挂载的目录覆盖。 原因 在Docker中,一旦使用COPY命令将文件复制到容器中,该文件就会被视为镜像的一部分,并且在运行容器时使用-v或--volume挂载宿主机目录到这个位置时,宿主机的内容将覆盖容器中的内容,导致挂载冲突。 方案1. 不挂载,只使用Dockerfile中的COPY:如果只关心构建时的操作而不需要在运行时修改文件,那么可以仅使用Dockerfile中的COPY命令,而不进行挂载。 version: '3' services: hexo: build: context: . dockerfile: Dockerfile image: chuchuzz426/blog-hexo:1.0 ports: - \"8080:80\" 这样构建时会将静态文件复制到镜像中,但在运行时对容器的/usr/share/nginx/html目录将不会受到冲突。 2. 分阶段处理:之所以要分阶段处理, 是因为构建过程中, 是没办法把内部文件拷贝或挂载到宿主机的,只能等构建完成后单独处理。 Dockerfile.build # 第一阶段:构建阶段 FROM node:14 AS builder WORKDIR /app COPY . . RUN npm install --no-fund && npx hexo clean && npx hexo generate # 第二阶段:导出静态资源到临时目录 FROM alpine as export WORKDIR /export COPY --from=builder /app/public /export/public # 运行构建 docker build -t myimage -f Dockerfile.build . # 创建一个临时容器,从中复制文件到宿主机 docker create --name extract myimage docker cp extract:/export/public ./public docker rm -f extract Dockerfile.run # 第三阶段:Nginx阶段 FROM nginx:alpine WORKDIR /usr/share/nginx/html COPY --from=export /export/public /usr/share/nginx/html EXPOSE 8080 然而这样的做法虽然能实现挂载, 但对我来说已经没有意义了 总结我的初衷是新发布的文章能在本地执行编译, 然后生成的静态文件资源能够和容器中的/usr/share/nginx/html互通, 避免本地每次发布新文章都要重新构建容器很麻烦, 但是现在回头想想, 其实写完新文章不想重新构建的话直接进入容器执行hexo g效果也一样的, 没白折腾, 又学到了有用的知识。","categories":[{"name":"Docker","slug":"docker","permalink":"http://chuchu-z.com/categories/docker/"}],"tags":[]},{"title":"MySQL索引事务","slug":"mysql-learn-02","date":"2024-02-19T01:53:36.000Z","updated":"2024-12-31T06:57:56.019Z","comments":true,"path":"posts/mysql-learn-02/","link":"","permalink":"http://chuchu-z.com/posts/mysql-learn-02/","excerpt":"索引与引擎及其关系索引 一种提高查询性能的数据结构, 类似于一本字典中的目录, 使得可以快速定位和检索数据位置, 具有以空间换时间的设计思想, 所以并不是任何情况都适合创建索引, 索引的价值是快速定位,如果起不到定位的字段通常是不需要创建索引的,因为索引会占用物理空间, 另外, 经常更新且不需要用作where条件的字段不必要创建索引, 数据频繁修改, 动态维护索引也需要额外的开销将影响数据库性能。","text":"索引与引擎及其关系索引 一种提高查询性能的数据结构, 类似于一本字典中的目录, 使得可以快速定位和检索数据位置, 具有以空间换时间的设计思想, 所以并不是任何情况都适合创建索引, 索引的价值是快速定位,如果起不到定位的字段通常是不需要创建索引的,因为索引会占用物理空间, 另外, 经常更新且不需要用作where条件的字段不必要创建索引, 数据频繁修改, 动态维护索引也需要额外的开销将影响数据库性能。 存储引擎 解决如何存储数据, 如何为存储的数据建立索引以及如何更新、查询数据等技术。 MySQL 存储引擎有 MyISAM 、InnoDB、Memory等, 其中 InnoDB 是在 MySQL 5.5 之后成为默认的存储引擎。 关系 存储引擎决定表的物理存储结构, 包括: 数据文件的格式、索引文件的格式, 包括如何组织数据、如何处理索引、如何处理事务、如何处理并发等。 而索引则是在这个物理存储结构上建立的数据结构, 不同的存储引擎可以支持不同类型的索引,例如B+树索引、B树索引、HASH索引。 InnoDB InnoDB数据按[数据页]为单位进行读写 InnoDB数据页默认大小为16KB, 所以InnoDB每次I/O操作数据最少操作16KB数据 数据页(图片来源小林coding) 索引划分 分类 索引类型 特点 说明 数据结构分类 B+Tree 索引 适用于等值查询和范围查询。 B+Tree 索引是一种平衡树结构,适用于范围查询和排序,是 MySQL 默认的索引类型。 HASH 索引 适用于等值查询,不支持范围查询,对于大数据量的表性能较好。 HASH 索引适用于等值查询,通过散列算法将索引列的值映射为散列值,对于大型数据集可以提供快速的查找。 Full-Text 索引 用于全文搜索,支持对文本数据进行高效的模糊查询。 Full-Text 索引是为了支持全文搜索,可以在文本数据中执行模糊查询,适用于需要搜索关键词的场景。 物理存储分类 聚簇索引(主键索引) 数据行的物理顺序与索引的顺序一致,InnoDB 存储引擎默认使用。 聚簇索引决定了数据在磁盘上的物理存储顺序,通常是主键索引。在 InnoDB 存储引擎中,表的数据行实际上是按照主键顺序存储的。 二级索引(辅助索引) 非主键索引,存储实际数据行的引用而不是实际的数据。 二级索引是不基于表的物理存储顺序的索引,而是存储指向实际数据行的引用。 字段特性分类 单列索引 仅基于单个列创建的索引。 单列索引是最基本的索引类型,没有唯一性或其他特殊约束,可以包含重复的值。 联合索引(复合索引) 基于多个列创建的索引,适用于同时查询多个列的情况。 联合索引可以包含多个列,有助于优化多列的查询条件。 唯一索引 确保索引列的值唯一,可用于强制实施表的唯一性约束。 唯一索引确保索引列中的值是唯一的,可用于强制表中的数据唯一性。 普通索引 基本索引类型,没有特殊约束,可以包含重复的值。 普通索引是最基本的索引类型,没有唯一性或其他特殊约束,可以包含重复的值。 前缀索引 仅对列的前几个字符创建索引,可减小索引的大小。 前缀索引是指对列的前几个字符创建的索引,用于减小索引的存储空间。 索引优化","categories":[{"name":"MySQL","slug":"mysql","permalink":"http://chuchu-z.com/categories/mysql/"}],"tags":[]},{"title":"24-02 笔记","slug":"24-02-note","date":"2024-02-18T02:26:41.000Z","updated":"2024-12-31T06:57:55.964Z","comments":true,"path":"posts/24-02-note/","link":"","permalink":"http://chuchu-z.com/posts/24-02-note/","excerpt":"新年已过, 今日初九, 开工大吉, 祝新的一年, 身体健康, 事业顺利 !!!","text":"新年已过, 今日初九, 开工大吉, 祝新的一年, 身体健康, 事业顺利 !!! 2.18 转眼2月已过半, 制定的计划仍未实施, 令人堪忧啊~ 2.19 打游戏 2.20 打游戏 2.21 打游戏 2.22 初初啊初初, 你怎能如此玩物丧志这样下去, 说好的计划呢😂 January 群友推荐 php:laravel 底层核心代码分析, 讲的挺好, 对反射类和依赖注入和控制反转等有进一步认识 在 小林coding MySQL基础篇深入理解一条sql的执行流程 把OSI 七层模型及TCP/IP 模型整理成表格 Django 框架学习","categories":[{"name":"岁月杂感","slug":"岁月杂感","permalink":"http://chuchu-z.com/categories/%E5%B2%81%E6%9C%88%E6%9D%82%E6%84%9F/"}],"tags":[]},{"title":"MySQL执行流程","slug":"mysql-learn-01","date":"2024-02-02T07:24:19.000Z","updated":"2024-12-31T06:57:56.019Z","comments":true,"path":"posts/mysql-learn-01/","link":"","permalink":"http://chuchu-z.com/posts/mysql-learn-01/","excerpt":"MySQL执行流程 连接器-查询缓存(如果是select才查询缓存, MySQL8.0废弃)-解析器(词法分析, 语法分析)-预处理器(判断表/字段是否存在)-优化器-执行器(验证权限, 调用存储引擎API, 如果有索引下推则携带索引条件给存储引擎判断-存储引擎查询数据并利用索引下推过滤数据, 然后执行回表查询数据, 向执行器(server层)返回结果)","text":"MySQL执行流程 连接器-查询缓存(如果是select才查询缓存, MySQL8.0废弃)-解析器(词法分析, 语法分析)-预处理器(判断表/字段是否存在)-优化器-执行器(验证权限, 调用存储引擎API, 如果有索引下推则携带索引条件给存储引擎判断-存储引擎查询数据并利用索引下推过滤数据, 然后执行回表查询数据, 向执行器(server层)返回结果) 分析器 分析器, 来自小林coding varchar字段最大取值计算公式 65535 - 变长字段字节数列表所占用的字节数 - NULL值列表所占用的字节数 = 65535 - 2 - 1 = 65532 如果有多个字段的话,要保证所有字段的长度 + 变长字段字节数列表所占用的字节数 + NULL值列表所占用的字节数 <= 65535 InnoDB 行格式及数据溢出处理方式 行格式 适用场景 存储空白列 行头大小 溢出处理 Compact 适用于索引列,OLAP 场景 不存储 固定 部分真实数据存储在数据页,溢出数据存储在溢出页中,通过指针连接溢出页 Dynamic 适用于非索引列,OLTP 场景 存储 可变 完全的行溢出方式,记录的真实数据处不存储该列的一部分数据,只存储 20 个字节的指针来指向溢出页 Compressed 适用于需要压缩存储的场景,Barracuda 存储 可变 完全的行溢出方式,记录的真实数据处不存储该列的一部分数据,只存储 20 个字节的指针来指向溢出页 在 Compressed 行格式中,如果数据行的大小超过了页的大小,InnoDB 存储引擎会使用分页压缩算法来减小数据的存储空间,但这并不是通过将溢出的数据存储在溢出页中来实现的。","categories":[{"name":"MySQL","slug":"mysql","permalink":"http://chuchu-z.com/categories/mysql/"}],"tags":[]},{"title":"OSI 七层模型及TCP/IP 模型","slug":"osi-model-and-tcp-ip-model","date":"2024-01-30T09:46:43.000Z","updated":"2024-12-31T06:57:56.020Z","comments":true,"path":"posts/osi-model-and-tcp-ip-model/","link":"","permalink":"http://chuchu-z.com/posts/osi-model-and-tcp-ip-model/","excerpt":"把OSI模型以及TCP/IP模型做成表格","text":"把OSI模型以及TCP/IP模型做成表格 OSI模型 层次 名称 功能作用 代表性协议 第七层(应用层) 应用层 (Application) 提供网络服务和用户接口,实现特定网络应用的通信 HTTP, FTP, SMTP, DNS, Telnet, SNMP 第六层(表示层) 表示层 (Presentation) 处理数据格式、编码和加密解密等,确保数据在不同系统之间的正确解释 SSL/TLS, JPEG, GIF, MPEG 第五层(会话层) 会话层 (Session) 管理会话或对话控制,建立、维护和终止应用程序之间的通信 NetBIOS, RPC, PPTP 第四层(传输层) 传输层 (Transport) 负责数据流的端到端通信,提供可靠的数据传输和错误检测,同时进行流量控制 TCP, UDP, SCTP 第三层(网络层) 网络层 (Network) 处理数据包的逻辑传输,提供路径选择和逻辑寻址,实现不同网络之间的路由 IP, ICMP, OSPF, BGP 第二层(数据链路层) 数据链路层 (Data Link) 提供物理寻址,错误检测和纠正,以及对物理介质的访问控制。分为逻辑链路控制(LLC)和介质访问控制(MAC)两个子层 Ethernet, PPP, HDLC, ARP 第一层(物理层) 物理层 (Physical) 在物理媒体上传输原始比特流,负责定义硬件设备和传输媒体的规范 Ethernet, USB, DSL, Bluetooth TCP/IP 模型 层次 名称 功能作用 代表性协议 第四层(应用层) 应用层 (Application) 提供网络服务和用户接口,实现特定网络应用的通信 HTTP, FTP, SMTP, DNS, Telnet, SNMP 第三层(传输层) 传输层 (Transport) 提供端到端的通信 TCP, UDP, SCTP 第二层(网络层) 网络层 (Internet) 处理数据包的逻辑传输,实现不同网络之间的路由 IP, ICMP, OSPF, BGP 第一层(网络接口层) 网络接口层 (Link) 负责物理寻址和介质访问控制 Ethernet, PPP, HDLC, ARP 计算机启动或连接到网络时涉及的协议、其功能作用以及执行阶段和层次的信息 阶段 协议 功能作用 执行阶段 层次 启动阶段 无协议 无 计算机电源启动 无 网络适配器初始化阶段 无协议 无 初始化网络适配器,加载适当的驱动程序 无 DHCP 获取网络配置阶段 DHCP 获取动态分配的网络配置,包括 IP 地址、子网掩码、默认网关、DNS 服务器等 计算机启动或连接到网络时 网络层(第三层) ARP 地址解析阶段 ARP 将目标设备的 IP 地址解析为对应的物理硬件地址(MAC 地址) 在需要进行局域网通信时 数据链路层(第二层) DNS 解析域名阶段 DNS 将域名解析为对应的 IP 地址 计算机启动或进行网络通信前 网络层(第三层) TCP 连接建立阶段 TCP 提供可靠的端到端通信 在建立连接和进行应用层通信时 传输层(第四层) 应用层通信阶段 HTTP、FTP、SMTP 等 实现特定网络应用的通信 计算机启动或进行网络通信时 应用层(第七层)","categories":[{"name":"Other","slug":"other","permalink":"http://chuchu-z.com/categories/other/"}],"tags":[]},{"title":"Python 使用 Django 框架","slug":"python-use-Django","date":"2024-01-15T01:41:42.000Z","updated":"2024-12-31T06:57:56.020Z","comments":true,"path":"posts/python-use-Django/","link":"","permalink":"http://chuchu-z.com/posts/python-use-Django/","excerpt":"有个项目需要用对接 ChatGpt 的API, 本来想拿老本行 PHP 写的, 但是 PHP 没有 Python 对接起来方便, 且我觉得语言只是工具, 每个语言都有它的优点和优势, 同时还能多多接触新东西, 利于学习。","text":"有个项目需要用对接 ChatGpt 的API, 本来想拿老本行 PHP 写的, 但是 PHP 没有 Python 对接起来方便, 且我觉得语言只是工具, 每个语言都有它的优点和优势, 同时还能多多接触新东西, 利于学习。 一. 初始化# 安装 pip install Django # 创建项目名 django-admin startproject your_project_name cd your_project_name # 创建应用名 python manage.py startapp your_app_name 二. 修改settings.py配置2.1 引入envimport os from pathlib import Path from dotenv import load_dotenv # 加载环境变量 load_dotenv() 2.2 配置数据库# Database # https://docs.djangoproject.com/en/5.0/ref/settings/#databases # mysql 版本使用5.7, 但Django要求8.0以上 # 全局搜索 check_database_version_supported ,并注释, 就不会检查mysql版本 # 位置大约在django/db/backends/base/base.py文件255行 DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': BASE_DIR / 'db.sqlite3', # } 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': os.getenv(\"DB_NAME\", ''), 'USER': os.getenv(\"DB_USER\", ''), 'PASSWORD': os.getenv(\"DB_PASSWORD\", ''), 'HOST': '127.0.0.1', # 或者是数据库服务器的IP地址 'PORT': '3306', # MySQL默认端口 'OPTIONS': { 'charset': 'utf8mb4', 'collation': 'utf8mb4_general_ci', # 'init_command': \"SET sql_mode='STRICT_TRANS_TABLES'\", }, } } 2.3 修改其他配置# 我的项目全是外部接口, 所以用不上表单和csrf, 注释csrf MIDDLEWARE = [ ... # 'django.middleware.csrf.CsrfViewMiddleware', ... ] 2.4 语言与时区LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' DATE_FORMAT = 'Y-m-d' DATETIME_FORMAT = 'Y-m-d H:i' USE_I18N = True USE_TZ = False 2.5 默认自增主键DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' 三. 使用Django# 数据迁移 python manage.py makemigrations python manage.py migrate # 启动服务器, 可指定端口或指定ip+端口 python manage.py runserver python manage.py runserver 8080 python manage.py runserver 0.0.0.0:8000 # 创建管理员 python manage.py createsuperuser # 搞定后登录管理 http://127.0.0.1:8000/admin/ 四. model示例 说实话, django的model和数据迁移做的真不好, 和laravel的migrate对比, 很多东西都不符合常理, 比如默认datetime(6), 还自带小数点 from django.db import models # 自定义 datetime 字段, 因为 django 默认datetime(6) class MySQLDateTimeField(models.DateTimeField): def db_type(self, connection): return 'datetime' class UploadedFile(models.Model): id = models.AutoField(primary_key=True) file_id = models.CharField(max_length=50, null=False, blank=True, db_default=\"\", db_comment=\"文件ID\") file_name = models.CharField(max_length=255, null=False, blank=True, db_default=\"\", db_comment=\"文件名\") file_size = models.IntegerField(null=False, db_default=0, blank=True, db_comment=\"文件大小\") file_status = models.CharField(max_length=50, null=False, blank=True, db_default=\"uploaded\", db_comment=\"文件状态\") file_purpose = models.CharField(max_length=50, null=False, blank=True, db_default=\"fine-tune\", db_comment=\"文件用途\") created_at = MySQLDateTimeField(auto_now_add=True, db_comment=\"创建时间\") objects = models.Manager() class Meta: db_table = \"chatgpt_upload_files\" indexes = [ models.Index(fields=[\"file_id\", \"file_status\", \"created_at\"], name=\"idx_file_id_status_create\"), # 联合索引 ] verbose_name = \"上传文件表\" verbose_name_plural = \"上传文件表\" def __str__(self): return self.file_id 五. 部署到服务器python3 -m venv venv source venv/bin/activate pip3 install -r requirements.txt 中途安装 mysqlclient 时报错参考了该博主文章解决: https://blog.csdn.net/qq_42336581/article/details/132244022","categories":[{"name":"Python","slug":"python","permalink":"http://chuchu-z.com/categories/python/"}],"tags":[]},{"title":"Python Django 接入 ChatGPT 模型训练/助理","slug":"exploring-ChatGPT-Integration-in-Python","date":"2024-01-06T02:19:17.000Z","updated":"2024-12-31T06:57:56.015Z","comments":true,"path":"posts/exploring-ChatGPT-Integration-in-Python/","link":"","permalink":"http://chuchu-z.com/posts/exploring-ChatGPT-Integration-in-Python/","excerpt":"ChatGPT 和 AI 的话题近两年都很火热, 自从 OpenAI 诞生出 ChatGPT 以来, 各互联网大厂公司纷纷加入并研发自家的AI大模型, 也有不少人趁着这个风口, 利用 ChatGPT 实现变现, 赚的盆满钵满, 瓜分这块AI蛋糕。","text":"ChatGPT 和 AI 的话题近两年都很火热, 自从 OpenAI 诞生出 ChatGPT 以来, 各互联网大厂公司纷纷加入并研发自家的AI大模型, 也有不少人趁着这个风口, 利用 ChatGPT 实现变现, 赚的盆满钵满, 瓜分这块AI蛋糕。 如何训练专属AI一是使用开源的大模型, 如 llama 和 ChatGLM-6B , 其中 ChatGLM-6B 我个人也比较喜欢, 优点是中文支持的比较好, 而且在自己的电脑上都能训练, 这部分还没有去研究, 下次有机会试试, 然后再发布 ChatGLM-6B 的训练方式 模型 训练数据 训练数据量 模型参数量 词表大小 LLaMA 以英语为主的拉丁语系,不包含中日韩文 1T/1.4T tokens 7B、13B、33B、65B 32000 ChatGLM-6B 中英双语,中英文比例为1:1 1T tokens 6B 130528 Bloom 46种自然语言和13种编程语言,包含中文 350B tokens 560M、1.1B、1.7B、3B、7.1B、176B 250880 模型 模型结构 位置编码 激活函数 layer norm LLaMA Casual decoder RoPE SwiGLU Pre RMS Norm ChatGLM-6B Prefix decoder RoPE GeGLU Post Deep Norm Bloom Casual decoder ALiBi GeLU Pre Layer Norm 二是接入ChatGpt, 也是本文的主角 通过上文得知, 训练 ChatGPT 的方式通常有两种办法, 一种是微调(fine-tuning), 一种是嵌入(embedding)。 大概流程就是由我们提供训练数据, 通过OpenAI官方文件上传接口给官方, 然后创建训练模型, 指定使用该文件给到该模型做训练 等训练完了之后, 我们就可以使用这个被训练过的模型与我们对话看看训练效果如何了 不想通过接口上传文件和创建训练模型的也可以登录OpenAI官方网站后, 在 https://platform.openai.com/files 和 https://platform.openai.com/finetune 操作也可以的 既然简单省事, 当然人家也不提供免费的午餐, 这是要收费的, 为啥收费的我还要用, 因为它训练参数更多更强, 不需要占用自己的服务器GPU, 更重要的是这是公司要求的接入 ChatGpt 使用Python接入OpenAI官方API文档 本次我是基于 gpt-3.5-turbo-1106 模型, 做微调(fine-tuning)训练, 接入微调训练不难, 难得是获取训练数据源以及数据的清洗和整合 由于微调缺乏大量训练数据, 转向了使用 助理 Assistants API 的方式实现, 成本更低, 也能能满足大部分的需求, 但本项目仍然支持微调(fine-tuning)训练 1.获取并设置秘钥创建一个OpenAI账号或登录。接下来,导航到API 密钥页面并“创建新密钥”, 拿到秘钥后, 添加到电脑环境变量里 1.1 Windows 添加秘钥 我的电脑-属性-高级系统设置-环境变量-系统变量-新建 保存后, win + R, 输入 cmd 回车, 并执行下面的命令, 输出秘钥则成功 echo %OPENAI_API_KEY% 1.2 Linux 添加秘钥vim ~/.bash_profile # 在文件的末尾添加以下行: export OPENAI_API_KEY='your-api-key' # 执行以下命令刷新配置生效 source ~/.bash_profile 2.部署# clone 代码 git clone [email protected]:chuchu-z/fine-tuning.git OpenAI # 切换到OpenAI目录 cd OpenAI # 为该项目创建独立的 Python 虚拟环境 python -m venv venv # 激活虚拟环境, 在 Unix/Linux 系统中 source venv/bin/activate # 激活虚拟环境, 在 Windows 系统中 .\\venv\\Scripts\\activate 或 source ./venv/Scripts/activate # 查看 sys.prefix, 是否在虚拟环境中 python -c \"import sys; print(sys.prefix)\" # 安装依赖 pip install -r requirements.txt # 启动, 指定ip和端口(仅开发环境填写0.0.0.0, 线上环境请根据实际情况修改) python manage.py runserver 0.0.0.0:9527 # 补充一个退出虚拟环境命令, 用不上的话就不用执行 deactivate 3.访问接口以chatgpt下的目录划分模块, 其中 common 是公共的一些操作, migrations 是数据迁移的模块, 其余的都是OpenAI的相关模块, 具体路由配置在 chatgpt/urls.py chatgpt |-- assistants # 助理API相关 |-- common # 公共内容 |-- file # 文件上传API相关 |-- fine_tuning # 微调API相关 |-- messages # 助理消息API相关 |-- migrations # 数据迁移 |-- runs # 运行线程API相关 `-- threads # 线程API相关 举例: 访问 /common/status请求URL: http://127.0.0.1:9527/common/status 说明: 查看状态, 能访问则说明应用启动成功 请求方式: GET 请求参数: 无 返回值: { \"info\": \"ok\", \"response\": {} } 4. 训练数据4.1微调训练数据格式微调(fine-tuning)训练要用到的数据格式为JSONL, 而不是标准的JSON, 不要搞混了 JSONL,全称为JSON Lines(或 JSONLines、JSON-L), 用于表示JSON对象的文本序列, 它与标准JSON格式略有不同,每行包含一个独立的JSON对象,而不是将它们包含在一个大的JSON数组中。每行都是有效的JSON,但整个文件可能不是一个有效的JSON数组。 4.2 jsonl示例数据lines{\"messages\": [{\"role\": \"system\", \"content\": \"Marv is a factual chatbot that is also sarcastic.\"}, {\"role\": \"user\", \"content\": \"What's the capital of France?\"}, {\"role\": \"assistant\", \"content\": \"Paris, as if everyone doesn't know that already.\"}]} {\"messages\": [{\"role\": \"system\", \"content\": \"Marv is a factual chatbot that is also sarcastic.\"}, {\"role\": \"user\", \"content\": \"Who wrote 'Romeo and Juliet'?\"}, {\"role\": \"assistant\", \"content\": \"Oh, just some guy named William Shakespeare. Ever heard of him?\"}]} {\"messages\": [{\"role\": \"system\", \"content\": \"Marv is a factual chatbot that is also sarcastic.\"}, {\"role\": \"user\", \"content\": \"How far is the Moon from Earth?\"}, {\"role\": \"assistant\", \"content\": \"Around 384,400 kilometers. Give or take a few, like that really matters.\"}]} {\"messages\": [{\"role\": \"system\", \"content\": \"Marv 是一个既真实又讽刺的聊天机器人。\"}, {\"role\": \"user\", \"content\": \"法国的首都是什么?\"}, {\"role\": \"assistant\", \"content\": \"巴黎,好像每个人都不知道这一点。\"}]} {\"messages\": [{\"role\": \"system\", \"content\": \"Marv 是一个既真实又讽刺的聊天机器人。\"}, {\"role\": \"user\", \"content\": \"谁写了'罗密欧与朱丽叶'?\"}, {\"role\": \"assistant\", \"content\": \"哦,只是一个叫威廉·莎士比亚的人。听说过他吗?\"}]} {\"messages\": [{\"role\": \"system\", \"content\": \"Marv 是一个既真实又讽刺的聊天机器人。\"}, {\"role\": \"user\", \"content\": \"从地球到月球距离有多远?\"}, {\"role\": \"assistant\", \"content\": \"大约384,400公里。再加减一点,好像也不是很重要。\"}]} 4.3 助理数据 检索可以利用模型外部的知识来增强助手,例如专有产品信息或用户提供的文档。文件上传并传递给助手后,OpenAI 将自动对文档进行分块、索引和存储嵌入,并实施矢量搜索以检索相关内容来回答用户查询。 简单来说就是, 我们只需要把文件上传上去给到助理, 它就会自动读取识别内容并学习模仿相关的内容来回复。 常见的支持文件格式有: 文件格式 MIME类型 .csv application/csv .docx application/vnd.openxmlformats-officedocument.wordprocessingml.document .html text/html .json application/json .md text/markdown .pdf application/pdf .txt text/plain .xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 更多支持的文件可查看官方: 支持的文件 参考资料https://gofly.v1kf.com/article/74 https://platform.openai.com/docs/guides/fine-tuning https://platform.openai.com/docs/api-reference/chat https://platform.openai.com/docs/api-reference/fine-tuning https://platform.openai.com/docs/api-reference/files/create https://cookbook.openai.com/examples/chat_finetuning_data_prep https://greatdk.com/1908.html https://github.com/wdkwdkwdk/CLONE_DK https://cn.v2ex.com/t/930423 https://udify.app/chat/RkCYZlpzZyhAsumL https://github.com/LC044/WeChatMsg/ https://blog.lc044.love/post/5 https://github.com/saturn-opposition/wechat_analysis","categories":[{"name":"Python","slug":"python","permalink":"http://chuchu-z.com/categories/python/"},{"name":"ChatGPT","slug":"python/chatgpt","permalink":"http://chuchu-z.com/categories/python/chatgpt/"}],"tags":[]},{"title":"谷歌翻译扩展失效 配置hosts解决","slug":"translate-google-hosts","date":"2024-01-03T06:27:19.000Z","updated":"2024-12-31T06:57:56.021Z","comments":true,"path":"posts/translate-google-hosts/","link":"","permalink":"http://chuchu-z.com/posts/translate-google-hosts/","excerpt":"因为谷歌关闭了中国大陆的谷歌翻译服务, 谷歌翻译扩展也停用了, 尽管我也想少用翻译软件, 多尝试自己阅读原文文档, 但不等于直接用不了一点啊啊啊","text":"因为谷歌关闭了中国大陆的谷歌翻译服务, 谷歌翻译扩展也停用了, 尽管我也想少用翻译软件, 多尝试自己阅读原文文档, 但不等于直接用不了一点啊啊啊 解决方案1. 修改hosts文件Win + E, 地址栏直接输入 C:\\Windows\\System32\\drivers\\etc 回车 编辑hosts文件, 从下面现用和备用中选一个加到文件最后 # 现用 203.208.40.66 translate.google.com 203.208.40.66 translate.googleapis.com # 如果上面的失效了, 可试试这个备用的 120.253.253.34 translate.googleapis.com 142.250.0.90 translate.googleapis.com 2. 刷新DNS然后 Win + R, 输入 cmd 回车, 执行下面的命令, 刷新DNS, 搞定! ipconfig /flushdns","categories":[{"name":"Other","slug":"other","permalink":"http://chuchu-z.com/categories/other/"}],"tags":[]},{"title":"HELLO-2024","slug":"hello-2024","date":"2024-01-02T01:43:42.000Z","updated":"2024-12-31T06:57:56.016Z","comments":true,"path":"posts/hello-2024/","link":"","permalink":"http://chuchu-z.com/posts/hello-2024/","excerpt":"新的一年, 希望今年有更好的成长","text":"新的一年, 希望今年有更好的成长 2024小目标工作1. 掌握hyperf、swoole 2. 系统深入学习MySQL, 搞懂底层锁, 事务, Buffer Pool等知识点 3. 系统学习计算机网络知识、通信协议 4. 继续在多邻国学习英语 5. 了解其他开发知识(Go,Oralce, 微服务) 生活/爱好1. 了解电脑硬件/系统装机等知识 2. 组装一台新电脑(耕升4070踏雪) 3. 沙盘战争红军/长征/抗美援朝部分 4. 多做饭 5. 《黑神话悟空》","categories":[{"name":"岁月杂感","slug":"岁月杂感","permalink":"http://chuchu-z.com/categories/%E5%B2%81%E6%9C%88%E6%9D%82%E6%84%9F/"}],"tags":[]},{"title":"无聊的年终总结","slug":"goodbye-2023","date":"2023-12-29T10:31:33.000Z","updated":"2024-12-31T06:57:56.016Z","comments":true,"path":"posts/goodbye-2023/","link":"","permalink":"http://chuchu-z.com/posts/goodbye-2023/","excerpt":"2023年就这么结束了, 今天是今年最后一天工作, 回想这一年, 也接触和了解到了很多新的东西, 即使成长的点滴虽小, 但不积跬步, 无以至千里 。","text":"2023年就这么结束了, 今天是今年最后一天工作, 回想这一年, 也接触和了解到了很多新的东西, 即使成长的点滴虽小, 但不积跬步, 无以至千里 。 今年做了什么 chatGpt 贯穿了我今年一整年的开发过程, 学习了如何跟它交流, 提取关键词提问, 获取信息 长达半年多的时间里, 从无到有, 学习了 Android studio 以及 webview App开发, 掌握 GooglePlay 商店 App 应用上架完整流程 学习众多有关于跨境电商知识, 接触较为有用的平台 sms-activate 、amzkeys、cloudflare 等 相比在安银的时候, 更加了解了 数字货币和钱包的交易关系 深入了解 websocket 、Nginx 代理、 反向代理、 PHP-FPM 与 Nginx 、PHP-CGI 等关系 五月二十三号, 正式开始踏入多邻国 并学习英语, 195天连胜打卡(准确来说, 应该只有150多天是每天都在学习的) 同五月份, 开始慢慢重视博客文章的编写, 十月份国庆开始接触学习计算机硬件知识 按年度来总结, 做的事情太多, 若不是提前规划好的事情, 最后能记住的事情太少, 能写下来的更少, 看来以后需要提前规划, 按月为单位来总结。 一个刚开始只会水溅跃💦的鲤鱼王, 最后是怎么进化成暴鲤龙的。","categories":[{"name":"岁月杂感","slug":"岁月杂感","permalink":"http://chuchu-z.com/categories/%E5%B2%81%E6%9C%88%E6%9D%82%E6%84%9F/"}],"tags":[]},{"title":" 个人docker-compose 配置","slug":"my-docker-zsh-config","date":"2023-12-26T09:15:00.000Z","updated":"2024-12-31T06:57:56.018Z","comments":true,"path":"posts/my-docker-zsh-config/","link":"","permalink":"http://chuchu-z.com/posts/my-docker-zsh-config/","excerpt":"前言 由于在 Windows 下开发 但是又想使用 zsh shell, 只好自己使用 docker 部署一套, 环境是搞好了, 但是还有个问题困扰着我","text":"前言 由于在 Windows 下开发 但是又想使用 zsh shell, 只好自己使用 docker 部署一套, 环境是搞好了, 但是还有个问题困扰着我 就是从 git-bash 里执行 docker exce 进入容器内部, 输入栏的光标位置与我实际输入的地方始终对不准 总是有一个空格的差距, 而在 docker desktop 里面的终端打开是正常的, 如下图, 仔细看就能发现 同样都是只输入了 vim , 在git-bash终端里面, 光标对准的位置却发生了偏差, 光标跑到了 vim a 那里去了 这个问题十分头疼 折腾许久找不到解决办法, 猜测是使用 agnoster.zsh-theme 主题的自带的特殊符号导致的, 因为尝试过删除特殊符号后就恢复了 但我仍无法解决如何在保留特殊符号的情况下不会出现那一个空格的偏差, 真是急死强迫症😓 这个难题就交给未来的我来解决吧 pull Codegit clone [email protected]:chuchu-z/docker-zsh.git 构建环境# 根据 docker-compose 配置构造镜像容器 docker-compose build --no-cache && docker-compose up -d # 启动 Zsh shell, 也可以把 zsh 改成 bash, sh, /bin/sh 等 winpty docker exec -it 11b3a0847350 zsh 补充 由于 .gitignore 忽略了 .ssh , pull 代码时记得加上该目录 cp ~/.ssh . 太久没用的话记得先去看看 docker-compose.yml 希望下次你能解决光标对齐问题 good luck~ 👍","categories":[{"name":"Docker","slug":"docker","permalink":"http://chuchu-z.com/categories/docker/"}],"tags":[]},{"title":"Windows10 激活产品密钥","slug":"windows-activation","date":"2023-12-26T01:37:20.000Z","updated":"2024-12-31T06:57:56.022Z","comments":true,"path":"posts/windows-activation/","link":"","permalink":"http://chuchu-z.com/posts/windows-activation/","excerpt":"帮同事电脑重装系统 需要激活产品密钥 网上有很多 但是很大部分都不可用 找了挺久 找到一个挺多人反馈可用的 记录下来看后面用不用的上","text":"帮同事电脑重装系统 需要激活产品密钥 网上有很多 但是很大部分都不可用 找了挺久 找到一个挺多人反馈可用的 记录下来看后面用不用的上 激活方法win+Q, 搜索cmd, 以管理员身份打开cmd工具, 按顺序执行下面4条命令, 也有人说把第三个命令行输入后去掉 http:// 只保留域名部分才可以成功 实在不行就去 设置-更新和安全-激活 里面激活, 产品密钥 W269N-WFGWX-YVC9B-4J6C9-T83GX slmgr /ckms slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX slmgr /skms http://kms.03k.org slmgr /ato 结语上面这个密钥不知道什么时候会失效, 以前也用过一些软件激活的, 现在想想这个东西, 其实就是写个循环 用枚举暴力破解, 假如我把网络上的产品密钥都收集起来放到一个文本文件里, 一个密钥一行, 脚本再一行一行的去读取该文本文件, 脚本循环执行上面的几行激活代码, 替换掉固定的密钥, 是不是也是一个自动激活工具呢","categories":[{"name":"Other","slug":"other","permalink":"http://chuchu-z.com/categories/other/"}],"tags":[]},{"title":"Python youtube-dl与you-get工具爬取视频","slug":"python-youtube-dl-and-you-get","date":"2023-12-25T03:23:21.000Z","updated":"2024-12-31T06:57:56.021Z","comments":true,"path":"posts/python-youtube-dl-and-you-get/","link":"","permalink":"http://chuchu-z.com/posts/python-youtube-dl-and-you-get/","excerpt":"youtube-dl 和 you-get 都是用于从互联网上下载视频的命令行工具,它们支持多种网站和服务 youtube-dl 功能更加全面,支持的网站更多,但也可能更复杂一些。 you-get 相对来说更简单,更容易上手,适用于一般用户。","text":"youtube-dl 和 you-get 都是用于从互联网上下载视频的命令行工具,它们支持多种网站和服务 youtube-dl 功能更加全面,支持的网站更多,但也可能更复杂一些。 you-get 相对来说更简单,更容易上手,适用于一般用户。 查看Python版本# 安装Python后 查看Python版本 python --version youtube-dl# 下载youtube-dl工具 pip install youtube-dl # 使用工具 youtube-dl --list-formats [url] # 列出可用的视频格式和质量 youtube-dl -oif [ -o 指定输出文件名或目录] [-i 忽略下载过程中的错误] [-f 指定下载的视频格式/质量, 如mp4] [url] you-get# 下载you-get工具 pip install you-get # 使用工具 you-get -F [url] # 列出可用的格式 you-get -i [url] # 显示视频信息 you-get -o <输出目录> <视频链接>","categories":[{"name":"Python","slug":"python","permalink":"http://chuchu-z.com/categories/python/"}],"tags":[]},{"title":"Docker 私有化部署 wiki-MrDoc","slug":"docker-deploy-wiki-MrDoc","date":"2023-12-19T03:52:09.000Z","updated":"2024-12-31T06:57:56.013Z","comments":true,"path":"posts/docker-deploy-wiki-MrDoc/","link":"","permalink":"http://chuchu-z.com/posts/docker-deploy-wiki-MrDoc/","excerpt":"为完善公司内部技术人员沟通以及共享信息文档, 使用wiki工具是很有必要的, 私有化部署可以避免信息外泄, MrDoc 是一款很不错的wiki工具, 有开源版以及功能更全的专业版 👉Gitee 地址 👉MrDoc 官方文档","text":"为完善公司内部技术人员沟通以及共享信息文档, 使用wiki工具是很有必要的, 私有化部署可以避免信息外泄, MrDoc 是一款很不错的wiki工具, 有开源版以及功能更全的专业版 👉Gitee 地址 👉MrDoc 官方文档 部署cd /www/wwwroot # close下来时顺便定义项目名称为wiki-Mrdoc git clone https://gitee.com/zmister/MrDoc.git wiki-Mrdoc # pull镜像 docker pull zmister/mrdoc:v7 # 注意修改挂载的项目目录为/www/wwwroot/wiki-Mrdoc docker run -d --name mrdoc -p 10086:10086 -v /www/wwwroot/wiki-Mrdoc:/app/MrDoc zmister/mrdoc:v7 # 创建用户 docker exec -it mrdoc python manage.py createsuperuser # 配置反向代理 server { listen 80; server_name wiki.chuchu-z.com; # 托管静态文件资源 location ^~ /static/ { alias /www/wwwroot/wiki-Mrdoc/static/; } # 配置反向代理 location / { proxy_pass http://127.0.0.1:10086; proxy_set_header Host $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 X-Forwarded-Proto $scheme; #Set Nginx Cache add_header Cache-Control no-cache; add_header X-Cache $upstream_cache_status; proxy_ignore_headers Set-Cookie Cache-Control expires; proxy_read_timeout 300; } } 迁移到其他服务器部署如果使用一段时间后, 需要将其部署到其他服务器 项目源代码在 /www/wwwroot/wiki-Mrdoc 目录下, 并且使用docker部署的 只需要将整个 wiki-Mrdoc 项目打包成压缩包文件, 并上传到其他服务器, 然后在新的服务器上执行部署命令 cd /www/wwwroot # 压缩 tar -czvf wiki-Mrdoc.tar.gz wiki-Mrdoc # 传输到新服务器 scp /www/wwwroot/wiki-Mrdoc.tar.gz root@{ip}:/www/wwwroot/ cd /www/wwwroot # 解压 .tar.gz 文件 tar -xzvf wiki-Mrdoc.tar.gz cd wiki-Mrdoc # pull镜像(先安装docker) docker pull zmister/mrdoc:v7 # 修改挂载的项目目录为/www/wwwroot/wiki-Mrdoc docker run -d --name mrdoc -p 10086:10086 -v /www/wwwroot/wiki-Mrdoc:/app/MrDoc zmister/mrdoc:v7 然后正常配置网站站点, 配置反向代理即可","categories":[{"name":"Docker","slug":"docker","permalink":"http://chuchu-z.com/categories/docker/"},{"name":"wiki","slug":"docker/wiki","permalink":"http://chuchu-z.com/categories/docker/wiki/"}],"tags":[]},{"title":"使用Docker安装hyperf-admin","slug":"use-Docker-install-hyperf","date":"2023-11-29T05:41:37.000Z","updated":"2024-12-31T06:57:56.021Z","comments":true,"path":"posts/use-Docker-install-hyperf/","link":"","permalink":"http://chuchu-z.com/posts/use-Docker-install-hyperf/","excerpt":"近期有项目用到 hyperf-admin, 顺便学习记录一下基于官方的镜像开始构建到部署过程 👉 hyperf官方地址","text":"近期有项目用到 hyperf-admin, 顺便学习记录一下基于官方的镜像开始构建到部署过程 👉 hyperf官方地址 安装&配置由于官方默认是在Linux执行的, 但实际我是在Win10下的 git-bash 终端执行, 所以命令稍微有点不一样, 比如指定项目路径的方式和不需要指定终端为 /bin/sh # 官方镜像 winpty docker run -v \"D:\\phpstudy\\WWW\\online-chat:/hyperf\" -p 9501:9501 -it hyperf/hyperf:7.4-alpine-v3.11-swoole # 官方镜像重制后的镜像 winpty docker run -v \"D:\\phpstudy\\WWW\\online-chat:/hyperf\" -p 9501:9501 -it chuchuzz426/hyperf:1.0 bash 执行完后进入容器内执行 #安装应用 apk add vim wget tzdata #修改时区为上海东八区 ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime echo \"Asia/Shanghai\" > /etc/timezone #输出时间查看 date #修改配置文件 vim ~/.bashrc #修改PS1 export PS1='\\[\\033]0;Bash\\007\\]\\n\\[\\033[32;1m\\] ➜ \\[\\033[33;1m\\]\\W\\[\\033[34;1m\\] [\\t] \\[\\033[36m\\]' #添加alias alias e='exit' alias www='cd /hyperf' alias ll='ls -al' alias vp='vim ~/.bashrc' alias sp='source ~/.bashrc' #保存后执行 source ~/.bashrc 由于 Docker 容器默认是以非交互式且不登录的情况进入容器的, 我们需要以交互式的情况进入 # 以 sh 方式启动 则需要在后面添加 -il 参数, 表示以交互式并且模拟登录的情况进入容器, 只有模拟登陆才会初始化执行 ~/.bashrc winpty docker exec -it e61fb6c63c38 sh -il # 以 bash 方式启动, 会默认初始化执行 ~/.bashrc文件 winpty docker exec -it e61fb6c63c38 bash 启动hyperf# 进入hyperf目录 cd /hyperf # 将 Composer 镜像设置为阿里云镜像,加速国内下载速度 composer config -g repo.packagist composer https://mirrors.aliyun.com/composer # 由于项目已经从github拉取下来 所以无需执行安装hyperf命令, 只需要执行composer update 获取依赖 composer update # 启动 Hyperf php bin/hyperf.php start # 浏览器输入http://127.0.0.1:9501访问 http://127.0.0.1:9501 Linux shell 配置文件关系表附带上文为什么修改 ~/.bashrc 原因, 因为想要在容器内定义一些alias命令, 而容器默认是非登录进入的, 所以说明一下初始化时读取的是哪个配置文件 文件 位置 作用和描述 ~/.profile 用户主目录 ($HOME) 用户登录时执行的个人配置文件。通常在登录时执行一次,用于设置用户环境变量和执行用户的个人配置。 ~/.bashrc 用户主目录 ($HOME) 非登录的 Bash shell 启动时执行的个人配置文件。用于设置 Bash shell 的特定配置,如别名、自定义函数等。 ~/.bash_profile 用户主目录 ($HOME) 用户登录时执行的个人配置文件。如果存在该文件,则通常会覆盖 ~/.profile。用于设置用户环境变量和执行用户的个人配置。 /etc/profile /etc/ 目录 系统级别的 Bash shell 配置文件。在系统启动时,用于设置全局环境变量和执行系统范围的配置。用户登录时也会执行一次。 把容器制作为镜像并导出为tar为了把修改过的容器方便在其他机器上使用, 打包制作成镜像 #容器制作为镜像 docker commit e61fb6c63c38 chuchuzz426/hyperf:1.0 #镜像导出为tar文件 docker save -o my-hyperf-image.tar chuchuzz426/hyperf:1.0 制作docker-compose.yml启动为了省去配置命令的麻烦和方便后续扩展, 添加docker-compose.yml文件 version: '3' x-project-settings: &project-settings project_name: hyperf-app services: hyperf-app: image: chuchuzz426/hyperf:1.0 container_name: hyperf ports: - \"9501:9501\" - \"9502:9502\" - \"9503:9503\" volumes: - D:\\phpstudy\\WWW\\online-chat:/hyperf working_dir: /hyperf/hyperf # command: [\"php\", \"bin/hyperf.php\", \"start\"] # 先执行一遍composer install command: - /bin/sh - -c - \"composer install && php bin/hyperf.php start\" 接下来就是 原神⭕🗽 hyperf, 启动! docker-compose up -d # 如果不是首次执行的话, 避免缓存问题最好执行这条 docker-compose build --no-cache && docker-compose up -d DB与redis连接配置 修改.env配置, 连接宿主机mysql, 先在宿主机执行 ipconfig 查看 WSL 的IPv4地址, 比如我的是172.21.240.1, 则 env配置文件的DB_HOST填写的就是172.21.240.1 如果mysql拒绝连接, 则修改一下mysql的用户授权 #用户授权,记得换成对应的库名和用户名及密码 GRANT ALL PRIVILEGES ON your_database.* TO 'your_username'@'%' IDENTIFIED BY 'your_password'; #刷新权限 FLUSH PRIVILEGES; redis连接宿主机同上, 记得确保 Redis 服务器的配置允许远程连接, 修改 redis.conf #只允许本地和 172.21.240.1 连接 bind 127.0.0.1 172.21.240.1 #允许任何ip连接, 不推荐,特别是在生产服务器上或者没设置密码的 bind 0.0.0.0 server配置在config/autoload/server.php的 server 配置如下, 端口具体根据实际情况修改 'servers' => [ [ 'name' => 'http', 'type' => Server::SERVER_HTTP, 'host' => '0.0.0.0', 'port' => 9502, 'sock_type' => SWOOLE_SOCK_TCP, 'callbacks' => [ Event::ON_REQUEST => [Hyperf\\HttpServer\\Server::class, 'onRequest'], ], ], [ 'name' => 'ws', 'type' => Server::SERVER_WEBSOCKET, 'host' => '0.0.0.0', 'port' => 9503, 'sock_type' => SWOOLE_SOCK_TCP, 'callbacks' => [ Event::ON_HAND_SHAKE => [Hyperf\\WebSocketServer\\Server::class, 'onHandShake'], Event::ON_MESSAGE => [Hyperf\\WebSocketServer\\Server::class, 'onMessage'], Event::ON_CLOSE => [Hyperf\\WebSocketServer\\Server::class, 'onClose'], ], ], ], VUE安装# 环境依赖 # 1. node ^v11.2.0 https://nodejs.org/zh-cn/download/ # 2. npm ^6.4.1 git clone https://github.com/hyperf-admin/hyperf-admin-frontend.git vue-admin cd vue-admin npm i npm run dev # 打包 npm run build:prod npm run build:test vue.config.js配置主要留意 module.exports 模块里的 devServer 和 proxy 配置要和hyperf对应上 module.exports = { /** * You will need to set publicPath if you plan to deploy your site under a sub path, * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/, * then publicPath should be set to "/bar/". * In most cases please use '/' !!! * Detail: https://cli.vuejs.org/config/#publicpath */ publicPath: '/', outputDir: 'dist', assetsDir: 'static', lintOnSave: process.env.NODE_ENV === 'development', productionSourceMap: false, devServer: { port: port, open: true, overlay: { warnings: false, errors: true }, proxy: { '/api': { target: 'http://127.0.0.1:9502', // 后台接口地址 ws: 'ws://127.0.0.1:9503', //如果要代理 websockets,配置这个参数 secure: false, // 如果是https接口,需要配置这个参数 changeOrigin: true, //是否跨域 pathRewrite:{ // 重写路径 '^/api':'' } } }, // before: require('./mock/mock-server.js') }, ... 生产环境留意 .env.production文件配置的 VUE_APP_BASE_API 域名改为线上域名","categories":[{"name":"Docker","slug":"docker","permalink":"http://chuchu-z.com/categories/docker/"},{"name":"hyperf","slug":"docker/hyperf","permalink":"http://chuchu-z.com/categories/docker/hyperf/"}],"tags":[]},{"title":"RabbitMQ简介(待补充)","slug":"lntroduction-to-RabbitMQ","date":"2023-10-20T03:34:11.000Z","updated":"2024-12-31T06:57:56.018Z","comments":true,"path":"posts/lntroduction-to-RabbitMQ/","link":"","permalink":"http://chuchu-z.com/posts/lntroduction-to-RabbitMQ/","excerpt":"近期学习了MQ, 打算记录一下个人的理解, 具体内容待补充","text":"近期学习了MQ, 打算记录一下个人的理解, 具体内容待补充 交换机类型死信交换机延迟交换机发布者的确认模式(交换机可靠性) 保证生产者消息能正确到达交换机 备用交换机 设置交换机持久化 发布者的返回模式(队列可靠性) 保证消息能从交换机正确到达队列 备用队列 设置队列持久化 交换机的属性队列的属性 消息在队列中不丢失, 设置消息持久化 消费者监听队列, 自动确认改为手动确认","categories":[{"name":"RabbitMQ","slug":"rabbitmq","permalink":"http://chuchu-z.com/categories/rabbitmq/"}],"tags":[]},{"title":"Android studio 缺少lombok 导致使用EvalEx错误","slug":"android-studio-use-lombok-and-evalex","date":"2023-09-20T03:34:11.000Z","updated":"2024-12-31T06:57:55.964Z","comments":true,"path":"posts/android-studio-use-lombok-and-evalex/","link":"","permalink":"http://chuchu-z.com/posts/android-studio-use-lombok-and-evalex/","excerpt":"另一篇中说了使用了代码混淆导致EvalEx扩展包失效, 其实在此之前, 还有一个问题, 那就是缺少了 lombok 库 不过该问题也比较有趣, 在debug的情况下打包生成app, 是不会触发错误提示缺少 lombok 库的, 一切都正常运行 在进行release打包的时候才会触发错误提示,但是在我写这篇文章时, 该问题已被解决, 具体错误描述没法放上来了","text":"另一篇中说了使用了代码混淆导致EvalEx扩展包失效, 其实在此之前, 还有一个问题, 那就是缺少了 lombok 库 不过该问题也比较有趣, 在debug的情况下打包生成app, 是不会触发错误提示缺少 lombok 库的, 一切都正常运行 在进行release打包的时候才会触发错误提示,但是在我写这篇文章时, 该问题已被解决, 具体错误描述没法放上来了 先看看ChatGPT是怎么介绍 lombok 的 Lombok是一个Java库,它可以通过注解来简化Java类的开发,并减少样板代码(boilerplate code)的编写。Lombok的目标是让Java开发者能够更加高效地编写简洁的代码,同时减少冗长的getter和setter方法、构造函数以及其他常见的样板代码。 使用Lombok,你可以在Java类中添加一些注解,以自动生成常见的代码块,例如: @Getter和@Setter:自动生成字段的getter和setter方法。 @ToString:自动生成toString()方法。 @EqualsAndHashCode:自动生成equals()和hashCode()方法。 @NoArgsConstructor:自动生成无参构造函数。 @RequiredArgsConstructor:自动生成包含必填字段的构造函数。 @AllArgsConstructor:自动生成包含所有字段的构造函数。 @Data:生成所有常见方法,如getter、setter、equals、hashCode等。 @Builder:用于构建器模式,自动生成建造对象的方法。 通过使用Lombok,开发者可以更专注于业务逻辑而不是编写重复的模板代码,从而提高代码的可读性和维护性。 要使用Lombok,你需要在项目中添加Lombok的依赖,并在你的Java类中引入Lombok的注解。然后,编译器会在编译时自动生成相关的代码。请注意,虽然Lombok可以提高开发效率,但它也可能会导致一些潜在的问题,因此在使用之前需要仔细了解其工作原理和限制。 经过上面的解释可以得知lombok是什么之后, 就要为EvalEx补上这个库了, 在翻找了一圈之后 找到了该库的 github地址: https://github.com/projectlombok/lombok 官方地址: https://projectlombok.org/all-versions 顺便补上EvalEx的github地址 : https://github.com/ezylang/EvalEx 因为我的Android studio 版本在Plugins里面搜是没有这个扩展可安装的, 只能手动安装 所以另外找到了两个如何安装lombok的方法 方法一: https://www.xjx100.cn/news/193686.html?action=onClick 方法二: https://zhuanlan.zhihu.com/p/597777983?utm_id=0 Lombok插件网站(jetbrains.com) : https://plugins.jetbrains.com/plugin/6317-lombok/versions 但是这上面2个方法呢, 因为版本的关系 比较麻烦, 要把压缩包改来改去, 没有直接能使用的 我就去stackoverflow上找了找 确实找到了一个有用的回答 https://stackoverflow.com/questions/72658652/plugin-lombok-is-not-compatible-with-current-version-of-ide-because-it-requires image-20230927163141841 给出了一个链接, 里面有 Lombok插件网站(jetbrains.com) 所没有的版本 Goto- lombok-compatible-versions image-20230927163400379 找到对应版本, 直接下载好压缩包之后, 在 Android studio 的 Plugins 里面 点击从磁盘里找到刚刚下载好的压缩包, 选择安装即可 image-20230927163810244 完成安装 image-20230927164022059 另外ChatGPT给我的建议是, 在项目目录下新建一个lombok.config文件, 并加入如下代码 以此来用来控制是否在 Lombok 生成的代码中添加 @javax.annotation.Generated 注解 lombok.addLombokGeneratedAnnotation = true","categories":[{"name":"Android","slug":"android","permalink":"http://chuchu-z.com/categories/android/"}],"tags":[]},{"title":"Android studio 使用R8 代码混淆 错误性缩减代码","slug":"android-studio-use-r8-shrink-code","date":"2023-09-20T02:44:11.000Z","updated":"2024-12-31T06:57:55.966Z","comments":true,"path":"posts/android-studio-use-r8-shrink-code/","link":"","permalink":"http://chuchu-z.com/posts/android-studio-use-r8-shrink-code/","excerpt":"最近开发了一个支持简单四则运算的计算器, 其中使用到了 com.ezylang:EvalEx 扩展包, 用于支持基本数学运算符的数学表达式, 开发阶段正常使用没有问题 然而当我开发完成打包签名时, 进行计算时就会出现错误","text":"最近开发了一个支持简单四则运算的计算器, 其中使用到了 com.ezylang:EvalEx 扩展包, 用于支持基本数学运算符的数学表达式, 开发阶段正常使用没有问题 然而当我开发完成打包签名时, 进行计算时就会出现错误 Operatorannotation for com.ezylang.evalex.operators.arithmetic PrefixPlusOperator’not found 大概就是说找不到com.ezylang.evalex里面的某个类, 然而, 我很确定的是在我开发阶段是没有任何问题的 经过对比, 确认是在release 配置中启用了代码混淆的问题, 先来看看官方对代码混淆的解释 👉 官方地址 可以看出, R8只做了3件事 代码/资源缩减 混淆 优化 其中, 我们重点关注代码缩减这个步骤 有意思的是, 后面还有一段说明, 表示: 在某些情况下,R8 很难做出正确判断,因而可能会移除应用实际上需要的代码 那么问题就很清晰了, 大概率是R8在做代码缩减时, 把 com.ezylang:EvalEx扩展包里我需要用到的东西当成无用代码给删掉了 so 👇 我们此时只需要在 proguard-rules.pro 文件, 加上一行, 表示保留com.ezylang.evalex包下的全部代码 -keep class com.ezylang.evalex.** { *; } 再次编译代码后, 四则运算计算器顺利执行 其实问题并不难, 但是若一开始被报错的内容所迷惑, 无从得知是R8的代码混淆造成的问题, 排查方向错了, 错误地把矛头指向com.ezylang.evalex, 可能在debug的路上越走越远, 最终放弃使用com.ezylang.evalex。 人生亦是如此🍺 PS: 补上 build.gradle.kts文件, 在buildTypes 中开启代码混淆配置, 完美收官💻 buildTypes { release { isMinifyEnabled = true // 启用代码混淆 // isShrinkResources = true // 启用资源缩减 proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) signingConfig = signingConfigs.getByName("release") } debug { isMinifyEnabled = false // 不启用代码混淆 // isShrinkResources = true // 启用资源缩减 proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) signingConfig = signingConfigs.getByName("debug") } } signingConfigs { create("release") { keyAlias = "key0" keyPassword = "pwd" storeFile = file("D:\\\\Android\\\\Projects\\\\pwd.jks") storePassword = "pwd" } }","categories":[{"name":"Android","slug":"android","permalink":"http://chuchu-z.com/categories/android/"}],"tags":[]},{"title":"Install Python3 and OpenSSL","slug":"install-python3","date":"2023-07-18T08:31:05.000Z","updated":"2024-12-31T06:57:56.018Z","comments":true,"path":"posts/install-python3/","link":"","permalink":"http://chuchu-z.com/posts/install-python3/","excerpt":"因为有个项目要用到 Python 爬取直播间主播和弹幕数据, 所以记录一下安装过程以及途中遇到的问题","text":"因为有个项目要用到 Python 爬取直播间主播和弹幕数据, 所以记录一下安装过程以及途中遇到的问题 先查看当前 Python 版本是2.7的, 后面要重新安装 Python3, 如果还没有安装过后面就更省事了 python –version #输出为 Python 2.7.16 OpenSSL Install#安装py3新版本之前先安装openssl, 否则后面缺少ssl又需要重装, 如果 /usr/local 目录下已经有 openssl 文件夹,先把openssl 改名为 opensslbak 备份, 防止后面出现问题能恢复 cd /usr/local mv openssl opensslbak wget https://www.openssl.org/source/openssl-3.0.2.tar.gz –no-check-certificate tar -zxvf openssl-3.0.2.tar.gz cd openssl-3.0.2/ ./Configure –prefix=/usr/local/openssl #一般上面命令都会失败报错:Can‘t locate IPC/Cmd.pm in xxx yum install -y perl-CPAN perl -MCPAN -e shell #进入后第一步选yes,第二步选manual,第三步选yes,出现 cpan[1]> 就可以了 install IPC/Cmd.pm #按Ctrl+D退出cpan,重新执行./Configure –prefix=/usr/local/openssl ./Configure –prefix=/usr/local/openssl make && make install cd /usr/local/openssl cp -rf /usr/local/openssl/lib64 /usr/local/openssl/lib Python3 install cd ~ wget https://www.python.org/ftp/python/3.12.1/Python-3.12.1.tar.xz tar -xvf Python-3.12.1.tar.xz yum update -y yum install -y zlib-devel bzip2-devel libffi-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make gcc gcc-c++ cd Python-3.12.1/ ./configure –prefix=/usr/local/python3 –with-openssl=/usr/local/openssl –with-openssl-rpath=auto #3个并发任务 make -j3 && make install cd /usr/local/bin/ #把原有的python2改成python.bak mv /usr/bin/python /usr/bin/python.bak 建立软链接 ln -s /usr/local/bin/python3 /usr/bin/python python –version #升级python版本之后将由默认的python指向了python3,yum不能正常使用,需要更改2个配置文件 vim /usr/bin/yum vim /usr/libexec/urlgrabber-ext-down 2个文件都是把开头第一行的 #!/usr/bin/python => #!/usr/bin/python2.7 注: 如果遇到了 php 程序正在使用openssl, 新安装的openssl缺少文件导致php那边报错看具体缺少哪个文件, 去原来的 opensslbak 文件夹里复制过来到现有的openssl对应的目录下然后重启一下Nginx和php就行了 pip Install pip install requests urllib3 pymysql websocket websocket-client mysql-connector-python pytz python-dotenv USE python LiveChatCrawler.py Error 1. pip is configured with locations that require TLS/SSL mkdir -p ~/.pip vim ~/.pip/pip.conf # 修改镜像源为阿里云 [global] index-url = http://mirrors.aliyun.com/pypi/simple/ [install] trusted-host = mirrors.aliyun.com 本文参考 CSDN 文章 => Caused by SSLError(“Can‘t connect to HTTPS URL because the SSL module is not available.“ 且在原基础上根据实际情况有所改动","categories":[{"name":"Python","slug":"python","permalink":"http://chuchu-z.com/categories/python/"}],"tags":[]},{"title":"利用 AutoHotKey 实现 win10 多显示器(扩展模式)快速切换","slug":"autohotkey-windows","date":"2023-05-25T09:15:04.000Z","updated":"2024-12-31T06:57:56.013Z","comments":true,"path":"posts/autohotkey-windows/","link":"","permalink":"http://chuchu-z.com/posts/autohotkey-windows/","excerpt":"在日常办公中我们经常会使用到外接显示屏来辅佐我们 提高办公效率 然而多显示屏每次切换屏幕都要用鼠标来移动切换, 对鼠标的依赖非常重且非常麻烦😡 尤其是我左边显示屏是 IDE 或者 shell 终端, 右边是浏览器 于是乎在知乎上看到一篇这样的文章👇","text":"在日常办公中我们经常会使用到外接显示屏来辅佐我们 提高办公效率 然而多显示屏每次切换屏幕都要用鼠标来移动切换, 对鼠标的依赖非常重且非常麻烦😡 尤其是我左边显示屏是 IDE 或者 shell 终端, 右边是浏览器 于是乎在知乎上看到一篇这样的文章👇 MoveMouseToMonitor请问win10接双显示器(扩展模式)怎么把鼠标游标切换到第二台显示器上? 看完这篇文章瞬间就觉得它能够完美解决我的问题, 于是乎我安装了答主分享的 MoveMouseToMonitor.exe 工具 然而使用过后似乎仍不能满足我的需求, 因为它仅仅实现了鼠标的光标由 A显示屏 👉 B显示屏 的移动 而实际的聚焦效果仍然保留在原来的 A显示屏 上 通俗易懂来讲就是 鼠标的聚焦 和 键盘的聚焦 是两码事 这样就导致我的鼠标光标从 shell 终端 或者 IDE 切换到浏览器后 输入键盘时, 实际的输出仍然会停留在 shell 终端 或者 IDE 的上 MoveMouseToMonitor V2.0这。。。实现了但没完全实现我想要的效果😂 于是我就花了亿点点时间研究了下 AutoHotKey 的语法和这个MoveMouseToMonitor.exe 程序的源代码 然后再此基础上做了一点点改动, 具体改动为当执行完 PerformMove 函数成功移动鼠标后 创建一个 ActivateWindowByMousePosition 函数, 获取当前鼠标位置的窗口 title WinActivate 会根据鼠标窗口的 title 来激活目标窗口, 把键盘的聚焦也切换到该窗口, 从而真正实现切换并激活窗口👍 PerformMove(MoveMonNum, OffX, OffY) { global MoveX, MoveY Gosub, CheckNumMonsChanged RestoreDPI := DllCall(\"SetThreadDpiAwarenessContext\", \"ptr\", -3, \"ptr\") SysGet, Coordinates%MoveMonNum%, Monitor, %MoveMonNum% Left := Coordinates%MoveMonNum%Left Right := Coordinates%MoveMonNum%Right Top := Coordinates%MoveMonNum%Top Bottom := Coordinates%MoveMonNum%Bottom If (OffX = -1) MoveX := Left + (Floor(0.5 * (Right - Left))) Else MoveX := Left + OffX If (OffY = -1) MoveY := Top + (Floor(0.5 * (Bottom - Top))) Else MoveY := Top + OffY DllCall(\"SetCursorPos\", \"int\", MoveX, \"int\", MoveY) Sleep, 10 DllCall(\"SetCursorPos\", \"int\", MoveX, \"int\", MoveY) DllCall(\"SetThreadDpiAwarenessContext\", \"ptr\", RestoreDPI, \"ptr\") Gosub, ActivateWindowByMousePosition Return } ActivateWindowByMousePosition: MouseGetPos, , , id, control WinGetTitle, title, ahk_id %id% WinActivate, %title% Return Github传送门👇https://github.com/chuchu-z/MoveMouseToMonitorV6","categories":[{"name":"Other","slug":"other","permalink":"http://chuchu-z.com/categories/other/"}],"tags":[]},{"title":"Hexo-Blog Docker搭建本地环境与持续集成","slug":"hexo-blog-build","date":"2023-05-22T09:59:58.000Z","updated":"2024-12-31T06:57:56.016Z","comments":true,"path":"posts/hexo-blog-build/","link":"","permalink":"http://chuchu-z.com/posts/hexo-blog-build/","excerpt":"Hexo-Blog (indigo-hexo6) 该博客使用了 GitHub Pages + Hexo + indigo-hexo6 主题 搭建 GitHub Pages 允许我们 创建以自己用户名开头的username.github.io仓库用来搭建自己的静态页面网站或者博客 而 Hexo 本身就是一款支持 Markdown 静态化博客框架 有多种主题可供选择 并且上手简单 刚好契合我的需求","text":"Hexo-Blog (indigo-hexo6) 该博客使用了 GitHub Pages + Hexo + indigo-hexo6 主题 搭建 GitHub Pages 允许我们 创建以自己用户名开头的username.github.io仓库用来搭建自己的静态页面网站或者博客 而 Hexo 本身就是一款支持 Markdown 静态化博客框架 有多种主题可供选择 并且上手简单 刚好契合我的需求 另外为了解决平时在写好文章想先本地预览 但是又不在自己电脑旁边或者使用公司电脑的时候要重新安装部署一遍 nodejs 和 hexo 这些东西 所以增加了docker来解决环境的问题 使用 Dockerfile + docker-compose 文件 DockerfileFROM node:14 AS builder WORKDIR /app COPY . . RUN npm install --no-fund && npx hexo clean && npx hexo generate FROM nginx:alpine WORKDIR /usr/share/nginx/html COPY --from=builder /app/public /usr/share/nginx/html EXPOSE 8080 提醒 在中国大陆由于某些众所周知的网络原因, npm install 命令有时候会失败, 可以多试几次, 也可以使用国内镜像或者科学上网安装 docker-composeversion: '3' services: hexo: build: context: . dockerfile: Dockerfile image: chuchuzz426/blog-hexo:1.0 ports: - "8080:80" 如此 git clone 下来的时候 能立马部署出一套本地环境 使用简单, 开袋即食😋 # 拉取src分支源码 git clone -b src [email protected]:chuchu-z/chuchu-z.github.io.git # 在项目目录执行 docker-compose build --no-cache && docker-compose up 然后就可以打开 http://127.0.0.1:8080/ 预览啦✨持续集成自动部署为了发布文章push 到 src 分支后能自动更新到博客, 使用了 GitHub Actions 来实现自动部署 通过使用 GitHub Actions,我们可以实现自动化的软件开发流程,提高开发效率和代码质量 它还可以帮助团队协同工作,确保代码的集成和部署过程更加可靠和一致 # Action 的名字 name: Hexo Auto Deploy on: # 触发条件1:src 分支收到 push 后执行任务。 push: branches: - src # 触发条件2:手动按钮 workflow_dispatch: # 这里放环境变量,需要替换成你自己的 env: # Hexo 编译后使用此 git 用户部署到 github 仓库 GIT_USER: chuchu-z # Hexo 编译后使用此 git 邮箱部署到 github 仓库 GIT_EMAIL: [email protected] # Hexo 编译后要部署的 github 仓库 GIT_DEPLOY_REPO: chuchu-z/chuchu-z.github.io # Hexo 编译后要部署到的分支 GIT_DEPLOY_BRANCH: master jobs: build: name: Build on node ${{ matrix.node_version }} and ${{ matrix.os }} runs-on: ubuntu-latest if: github.event.repository.owner.id == github.event.sender.id strategy: matrix: os: [ubuntu-latest] node_version: [14] steps: - name: Checkout uses: actions/checkout@v2 - name: Checkout deploy repo uses: actions/checkout@v2 with: repository: ${{ env.GIT_DEPLOY_REPO }} ref: ${{ env.GIT_DEPLOY_BRANCH }} path: .deploy_git - name: Use Node.js ${{ matrix.node_version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node_version }} - name: Configuration environment env: HEXO_DEPLOY_PRI: ${{secrets.HEXO_DEPLOY_PRI}} run: | sudo timedatectl set-timezone \"Asia/Shanghai\" mkdir -p ~/.ssh/ echo \"$HEXO_DEPLOY_PRI\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts # coding 已取消同步 ssh-keyscan -t rsa e.coding.net >> ~/.ssh/known_hosts ssh-keyscan -t rsa gitee.com >> ~/.ssh/known_hosts git config --global user.name $GIT_USER git config --global user.email $GIT_EMAIL - name: Install dependencies run: npm install --no-fund - name: Deploy hexo run: | npm run deploy 触发条件为每当有push 代码的时候将自动按照.github/workflows/deploy.yml下的配置文件构造部署环境 相当于帮我们执行了 hexo generate 和 hexo deploy 然后hexo deploy会根据项目根目录下的_config.yml配置文件 把编译好的静态文件更新到以自己用户名开头的username.github.io仓库的 master 分支上 这样就完成了自动化部署啦 deploy: type: git # repo: [email protected]:chuchu-z/chuchu-z.github.io.git #构建机器上没有配置 ssh 免密,所以使用https repo: https://[email protected]/chuchu-z/chuchu-z.github.io.git branch: master message: GitHub Actions 自动部署:{{ now('YYYY-MM-DD HH:mm:ss') }} 👉 博客地址: http://chuchu-z.com👉 GitHub地址: https://github.com/chuchu-z/chuchu-z.github.io","categories":[{"name":"Docker","slug":"docker","permalink":"http://chuchu-z.com/categories/docker/"}],"tags":[]},{"title":"[教程] Android Webview 开发(App内嵌web)","slug":"android-webview-develop","date":"2023-05-16T11:31:05.000Z","updated":"2024-12-31T06:57:55.970Z","comments":true,"path":"posts/android-webview-develop/","link":"","permalink":"http://chuchu-z.com/posts/android-webview-develop/","excerpt":"自己花了2周的时间慢慢摸索出来的一点点经验, 网上教程很多, 但更多的是搬运或者年份比较久远的了, 借着着ChatGPT和网上的方法总算把项目搞定了, 打算把从开发到上架Google Play的全流程记录下来方便回顾总结, 同时希望对大家有一点点帮助。","text":"自己花了2周的时间慢慢摸索出来的一点点经验, 网上教程很多, 但更多的是搬运或者年份比较久远的了, 借着着ChatGPT和网上的方法总算把项目搞定了, 打算把从开发到上架Google Play的全流程记录下来方便回顾总结, 同时希望对大家有一点点帮助。 另外安装 Android studio 教程就不出了, 实在是不想卸载了重新安装一遍, 需要安装教程的伙伴们可以参考知乎这位大佬写的教程 全网最全最细Android Studio 安装和使用教程 , 不过这个教程的第三步, <SDK的安装> 建议跳过, 直接看第四步 <Android模拟器的下载> , 因为现在新版本 Android studio 里面已经集成SDK安装了, 不需要去单独下载, 可能是这位大佬当时是旧版本还没有集成到。 一. 创建项目选择 Empty Activity 1. Package namePackage name 尽量不要使用默认的 com.example 开头, 起个正经点的名字, 特别是如果后续想要打包发布到 google paly 上面的, com.example 开头是不会通过的, 到时候还得代码里各种改一遍包名, 然后还可能会有莫名其妙的缓存问题因为包名改了导致各种报错, 算是一个小小的坑, 尽量一开始定好就不要改动。 2. Minimum SDK关于SDK的选择, 尽量选择稍微低版本的SDK, 这样能支持的设备就更多一些, 如果是个人项目练习的可以随意, 如果公司项目的话尽量选择能支持多设备的, 一般能支持95%以上差不多可以了, 具体看公司要求, 本人这里选择的是API 28。 3. Build language构建语言选择, Kotlin 是 Android 开发的推荐语言,它提供了现代化的语言特性、更好的性能和良好的工具支持。而 Groovy 在 Android 开发中的使用相对较少,主要适用于特定场景或个人喜好。选择哪种语言取决于个人偏好、项目需求和团队情况 。本人推荐选择Kotlin, 选择完点击 Finish ,会自动进行项目初始化,耐心等待一会就好了 。 二. 目录结构及重要文件初始化好后, 可以点击左上角切换项目以什么形式展开, Project形式能更详细看到每个文件和目录, Android形式会简化很多不必要的文件夹,看起来更加简洁舒适 。目录结构介绍较长, 着急下一步安装的可以直接跳到第三步 SDK安装 , 后续再回来看结构介绍。 WebView 项目通常遵循以下目录结构: - app/ |- src/ | |- main/ | |- java/ | | |- com.example.app/ # 应用的代码 | | | |- MainActivity.java # 主Activity文件 | | | |- res/ | | |- layout/ # 布局文件 | | | |- activity_main.xml | | | | | |- values/ # 值资源文件 | | | |- strings.xml # 字符串资源文件 | | | |- AndroidManifest.xml # 应用程序清单文件 | | |- assets/ # WebView使用的本地资源 | | |- index.html # WebView入口HTML文件 | | |- css/ # CSS样式文件 | | |- js/ # JavaScript脚本文件 | | |- images/ # 图片文件 | |- ... |- build.gradle.kts # 项目的Gradle构建配置文件 |- ... 1. com.example.app我们一般情况主要开发都是在com.example.app下面进行的, 主要代码基本都在这里, 这里说明一下, 如果是新版本的Android studio初始化的时候, 默认是使用Kotlin 语言进行开发的, 所以主Activity文件会是 MainActivity.kt而不是 MainActivity.java, 不管是Kotlin还是Java, 选择哪个作为应用的开发语言都可以的, 而且这两个语言是可以相互转换的, 用Java的话可以删掉MainActivity.kt, 自己新建 MainActivity.java。 Kotlin 是一种现代的、静态类型的编程语言,与 Java 语言可以在 Android 开发中无缝集成。它提供了更简洁、安全、表达力强的语法,并具有许多特性和功能,可帮助开发者更高效地编写 Android 应用程序。 2. AndroidManifest.xml重要: AndroidManifest.xml 是 Android 应用程序的 核心配置文件,它描述了应用程序的基本信息、组件、权限和行为等。在开发 Android 应用程序时,清单文件的正确配置和使用非常重要,它直接影响应用程序的功能和行为。 <?xml version=\"1.0\" encoding=\"utf-8\"?> <manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:tools=\"http://schemas.android.com/tools\"> <!-- 权限声明:通过 <uses-permission> 元素,你可以声明应用程序需要的权限。Android 操作系统会在安装应用程序时向用户展示所请求的权限,并在用户同意后授予应用程序相应的权限。 --> <uses-permission android:name=\"android.permission.INTERNET\" /> <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" /> <uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" /> <!-- <application> 元素用于定义应用程序的全局配置和属性 --> <application android:allowBackup=\"true\" android:dataExtractionRules=\"@xml/data_extraction_rules\" android:fullBackupContent=\"@xml/backup_rules\" android:icon=\"@mipmap/ic_launcher\" android:label=\"@string/app_name\" android:roundIcon=\"@mipmap/ic_launcher_round\" android:supportsRtl=\"true\" android:theme=\"@style/Theme.MyWebview\" tools:targetApi=\"31\"> <!-- <activity> 元素用于声明应用程序的活动(Activity)。每个活动都需要在清单文件中进行声明,以便在应用程序中使用 android:name: 指定活动的类名(默认MainActivity.java) android:theme:指定活动的主题样式 --> <activity android:name=\".MainActivity\" android:exported=\"true\" android:label=\"@string/app_name\" android:theme=\"@style/Theme.MyWebview\"> <!-- 用于指定一个活动(Activity)作为应用程序打开时的主要入口点, 不可有多个, 多个的话安装app时桌面会出现多个应用图标 --> <intent-filter> <action android:name=\"android.intent.action.MAIN\" /> <category android:name=\"android.intent.category.LAUNCHER\" /> </intent-filter> </activity> </application> </manifest> 3. res/ 目录在 Android 项目中的 res/ 目录是用于存放资源文件的目录,其中包含了应用程序所需的各种资源,如布局文件、字符串、图像、颜色、样式等。这个目录是在 Android 项目创建时自动生成的,用于组织和管理应用程序的静态资源,在这些目录中,我们可以根据资源的类型和用途将相应的文件放置在相应的目录中,以便在代码中引用和使用这些资源。 res/ 目录通常包含以下子目录: - res/ |- layout/ # 用于存放布局文件,定义了应用程序的用户界面的组件和布局结构。 |- drawable/ # 用于存放图像资源文件,如位图文件(.png、.jpg、.gif 等)或矢量图形文件(.xml)。 |- mipmap/ # 用于存放应用程序图标的不同分辨率版本。通常包括 `mdpi`、`hdpi`、`xhdpi`、`xxhdpi`、`xxxhdpi` 等不同密度的图标文件。 |- values/ # 用于存放资源值文件,如字符串、颜色、尺寸、样式等。包括 `strings.xml`、`colors.xml`、`dimens.xml`、`styles.xml`。 |- raw/ # 用于存放原始资源文件,如音频文件、视频文件、字体文件等。这些文件可以直接通过资源 ID 访问。 |- menu/ # 用于存放菜单资源文件,定义应用程序的菜单结构。 |- xml/ # 用于存放其他 XML 文件,如自定义视图、插件配置文件等。 4. build.gradlebuild.gradle.kts 是使用 Kotlin 脚本语言编写的 Android 项目的构建脚本文件,用于配置和管理项目的构建过程。如果一开始创建项目时选的是Groovy, 那么生成的就是 build.gradle 文件,两者相比, build.gradle.kts 提供了使用 Kotlin 语言进行更灵活、类型安全和可编程的构建配置。 在 build.gradle.kts 文件中,我们可以定义项目的依赖关系、插件应用、构建类型、任务配置等。 build.gradle.kts 文件的基本结构: // 构建脚本的基本信息和配置 plugins { id(\"com.android.application\") version \"7.0.0\" // 其他插件的应用 } android { // Android 构建的配置 compileSdk = 33 //应用程序的编译目标版本 defaultConfig { applicationId = \"com.example.myapp\" minSdk = 28 //最低支持的 Android 版本 targetSdk = 33 //目标设备的 Android 版本 versionCode = 1 versionName = \"1.0\" } // 其他 Android 构建配置 } dependencies { // 依赖关系配置 implementation(\"com.android.support:appcompat-v7:28.0.0\") // 其他依赖项 } // 自定义任务配置 tasks { // 自定义任务的配置 val myTask by registering { // 任务的配置 } // 其他任务配置 } 三. SDK安装1. SDK目录在 Android 开发中,SDK Platforms 是用于开发和构建 Android 应用程序所需的 Android 平台版本。安装 SDK Platforms 是为了能够编译和运行应用程序的目标 Android 版本。例如,如果你开发的应用程序目标版本是 Android 10(API 级别 29),你应该选择安装对应的 Android 10 SDK Platforms。 建议目录结构如下, 管理起来方便一些: - d/ |- Android/ |- Projects # 项目目录,所有开发的项目可以放到此目录下 |- SDK # SDK目录 |- Studio # Android Studio 安装目录 2. 环境变量配置点击我的电脑 -> 属性 -> 高级系统设置 -> 环境变量 -> 新建系统变量 创建2个系统变量 ANDROID_SDK_ROOT => D:\\Android\\SDK ANDROID_ADB => D:\\Android\\SDK\\platform-tools 把刚创建的系统变量添加到Path变量中 %ANDROID_SDK_ROOT% %ANDROID_ADB% 3. SDK安装点击左上角的 File -> Settings -> System Settings -> Android SDK, 安装目录可以像我这样, 如果我们的应用要在Android 10 运行就找到 Android 10 勾选上, 如果你的应用还要在其他Android版本上运行, 也可以把其他版本安装一下, 选完后点击Apply 耐心等待安装完成即可。 注意: 后面安装虚拟设备的时候也是在SDK的基础上安装的 举例: 如果你没有安装Android 13的SDK, 那也没有办法安装和使用Android 13的虚拟设备, 另外安装虚拟设备时有的可能还需要用到 Google APIs 镜像的, 可以点击右下角的 Show Package Details 查看, 根据虚拟设备所需要的Google APIs 来勾选安装。 4. SDK Tools 安装 Android SDK Build-Tools:构建和编译Android应用程序所必需的工具集,包括编译器、调试器和其他构建工具。 Android SDK Platform-Tools:这是与Android设备通信、调试和管理的一组工具,如adb(Android Debug Bridge)、fastboot等。 Android Emulator:模拟Android设备的工具,用于在开发计算机上运行和测试Android应用程序。 Android Emulator Hypervisor Driver 和 Intelx6 Emulator Accelerator(HAXM installer) 都是加速 Android 模拟器用于提高 Android 模拟器性能的组件。 其他的非必选 各位实际项目需求来, 另外可能Android Studio版本不同, 下图的工具名称可能也有所不同甚至没有这个工具换成其他的替代了。 四. 虚拟设备安装1. 选择安装镜像点击右上角的 Device Manager(手机机器人图标) -> Create Device (创建设备) , 在 phone 这一栏选择一个符合你要求的, 然后点击 NEXT 进入到具体得镜像选择, 选择好后继续点NEXT后再点击Finish等待安装完成就可以了 前面安装SDK时说过, 创建虚拟设备跟我们安装的SDK还有镜像有关, 在这里选择镜像的时候有的选项就会置灰不可选择, 因为你没有安装该虚拟设备所需要的Android SDK版本或者 镜像 2. 启动虚拟设备安装好之后, 如下图, 点击 Actions 即可启动虚拟设备 五. 启动项目经过前面的铺垫, 现在终于可以进入开发阶段了, 如果前面一切顺利的话, 现在只需要点击一下右上角的Run app , 项目就会运行起来, 然后就可以在虚拟设备的界面上看到Hello Android!","categories":[{"name":"Android","slug":"android","permalink":"http://chuchu-z.com/categories/android/"}],"tags":[]},{"title":"浅记冒泡排序及斐波那契数列优化点","slug":"bubble-sort-and-fibonacci","date":"2023-02-16T11:04:13.000Z","updated":"2024-12-31T06:57:56.013Z","comments":true,"path":"posts/bubble-sort-and-fibonacci/","link":"","permalink":"http://chuchu-z.com/posts/bubble-sort-and-fibonacci/","excerpt":"冒泡排序 一般的冒泡排序只能满足最基本的要求, 如果不加以优化, 还会多做无用功, 出现重复循环的无效排序。","text":"冒泡排序 一般的冒泡排序只能满足最基本的要求, 如果不加以优化, 还会多做无用功, 出现重复循环的无效排序。 常规冒泡排序**<?php $arr = [2,-3,-10,4,-5,6,7,8,12,9,1,-11,100,-200,300,400,500]; $len = count($arr); for($i = 0; $i < $len - 1; $i++) { for($j = 0; $j < $len - $i - 1; $j++) { if ($arr[$j] > $arr[$j + 1]) { $item = $arr[$j]; $arr[$j] = $arr[$j + 1]; $arr[$j+1] = $item; } } } var_dump($arr); 优化点1 如 [1,2,3,5,4 ] , 只需要排序一遍的, 我们可以增加标识位表示当前是有序或无序,已经是有序的情况可直接退出循环。 <?php $arr = [2,-3,-10,4,-5,6,7,8,12,9,1,-11,100,-200,300,400,500]; $len = count($arr); $index = $len - 1;//排序下限 $maxIndex = 0; //排序上限 for($i = 0; $i < $len - 1; $i++) { //定义标识位标记已经有序或无序 $flag = true; for($j = 0; $j < $len - $i - 1; $j++) { if ($arr[$j] > $arr[$j + 1]) { $item = $arr[$j]; $arr[$j] = $arr[$j + 1]; $arr[$j+1] = $item; $flag = false; } } // 优化1,无排序即完成,可退出 if ($flag) { break; } } var_dump($arr); 优化点2 当一个数组接近有序的时候, 只需要在某一个小范围内排序即可, 如 [1, 7,5,3,9,11,12,13,14] , 在11后面都已经是有序的情况, 11后面的无需再排序, 可以使用标记来表示这个范围的下限, 只排序到此下标位置即可。 <?php $arr = [2,-3,-10,4,-5,6,7,8,12,9,1,-11,100,-200,300,400,500]; $len = count($arr); $index = $len - 1;//排序下限 $maxIndex = 0; //排序上限 for($i = 0; $i < $len - 1; $i++) { //定义标识位标记已经有序或无序 $flag = true; for($j = 0; $j < $index; $j++) { if ($arr[$j] > $arr[$j + 1]) { $item = $arr[$j]; $arr[$j] = $arr[$j + 1]; $arr[$j+1] = $item; $flag = false; $maxIndex = $j; } } // 优化1,无排序即完成,可退出 if ($flag) { break; } /** * 优化2 * 当一个数组接近有序的时候 * 只需要在某一个小范围内排序即可 * 使用标记来表示这个范围的下限 * 只排序到此下标位置即可 */ $index = $maxIndex; } var_dump($arr); 斐波那契数列斐波那契数列递归<?php function fibonacci($n) { if($n <= 0) return 0; if($n == 1 || $n == 2) return 1; return fibonacci($n - 1) + fibonacci($n - 2); } // 经过测试, 使用该方法当计算数值达到30以上运算会肉眼可见的明显变慢 for($i = 0; $i < 30; $i++) { var_dump(fibonacci($i)); } 递归优化 从上面的递归方法可以看到,进行了很多的重复计算,性能极差,N越大,计算的次数越多,既然因为重复计算影响了性能,那么优化就从减少重复计算入手,即把之前计算的存储起来,这样就避免了过多的重复计算,优化了递归算法(但仍然不推荐使用递归)。 <?php function fibonacci_2($n = 1, $a = 1, $b = 1) { if ($n <= 0) return 0; if ($n > 2) { // 存储前一位,优化递归计算 return fibonacci_2($n - 1, $a + $b, $a); } return $a; } // 优化后500内的计算0.2090780735s内可算出来 for($i = 0; $i < 500; $i++) { var_dump(fibonacci_2($i)); } 非递归写法(记忆化自底向上) 自底向上计算, 把结果存储到数组中, 避免重复计算。 <?php function fibonacci_3($n) { if ($n <= 0) return 0; if ($n <= 2) return 1; $list = [0, 1, 1]; for ($i = 3; $i <= $n; $i++) { $list[$i] = $list[$i - 1] + $list[$i - 2]; } return $list[$n];// 返回最后一个数,即第N个数 } for($i = 0; $i < 500; $i++) { var_dump(fibonacci_3($i)); } 动态规划 进一步优化, 没必要将结果存储到一个数组, 利用动态规划思想, 定义临时变量解决。 动态规划的思想是,记录中间计算结果,计算后面时,根据前面保存的结果直接计算,避免重复计算且减少存储空间占用。 <?php function fibonacci_4($n) { if ($n <= 0) return 0; if ($n <= 2) return 1; $a = 0; $b = 1; for ($i = 1; $i < $n; $i++) { $b = $a + $b; $a = $b - $a; } return $b; } for($i = 0; $i < 500; $i++) { var_dump(fibonacci_4($i)); }","categories":[{"name":"Other","slug":"other","permalink":"http://chuchu-z.com/categories/other/"}],"tags":[]},{"title":"GitHub Actions实现Hexo自动化部署","slug":"hexo-blog-git-actions","date":"2023-02-13T21:24:23.000Z","updated":"2024-12-31T06:57:56.016Z","comments":true,"path":"posts/hexo-blog-git-actions/","link":"","permalink":"http://chuchu-z.com/posts/hexo-blog-git-actions/","excerpt":"前言 由于半夜睡不着,突然想到博客很久没有更新了, 准备把很久之前写好的文章发布一下,但是发现原来使用的 travis-ci 没有触发, 去查了一下才知道 Travis CI 在 2020年 11 月 2 日就改变了收费策略 ,原来我现在用的免费方案,系统会赠送 10000 积分(一次性)。","text":"前言 由于半夜睡不着,突然想到博客很久没有更新了, 准备把很久之前写好的文章发布一下,但是发现原来使用的 travis-ci 没有触发, 去查了一下才知道 Travis CI 在 2020年 11 月 2 日就改变了收费策略 ,原来我现在用的免费方案,系统会赠送 10000 积分(一次性)。 Linux 机器上每分钟消耗 10 积分,macOS 机器上每分钟消耗 50 积分,我的积分已经消耗完了。一开始我觉得比较诧异,因为我以前从来没关注有这个积分机制,以为公共仓库使用 Travis CI 服务都是免费的。被迫无奈,本来只是想发个文章,变成了连夜更换CI/CD,中途还发现域名快到期了顺便续了一年😥。 Hexo 持续集成由于本人是通过GitHub Pages方式来实现博客托管的,好处是不需要自己购买服务器和域名, 只需要在github上创建一个repository,这个repository的名字还有要求必须是username.github.io,再随便写个静态html内容上传就可以直接访问了,具体方法这里不再多说。 先简单介绍一下项目仓库,源代码和hexo编译后的静态资源都在同一仓库(chuchu-z.github.io), 只是分支不同,src分支为源代码仓库, master分支为hexo编译后的静态资源, 也就是博客展示出来的内容。 生成公钥私钥ssh-keygen -t rsa -C "$(git config user.name)" -f github-deploy-key 添加仓库环境变量设置 HEXO_DEPLOY_PUB,value 是上步生成的 github-deploy-key.pub 文件内容。 设置 HEXO_DEPLOY_PRI,value 是上步生成的 github-deploy-key 文件内容。 编写配置文件deploy.yml在 myblog 项目根目录下创建 .github/workflows/deploy.yml 文件。 # Action 的名字 name: Hexo Auto Deploy on: # 触发条件1:src 分支收到 push 后执行任务。 push: branches: - src # 触发条件2:手动按钮 workflow_dispatch: # 这里放环境变量,需要替换成你自己的 env: # Hexo 编译后使用此 git 用户部署到 github 仓库 GIT_USER: chuchu-z # Hexo 编译后使用此 git 邮箱部署到 github 仓库 GIT_EMAIL: [email protected] # Hexo 编译后要部署的 github 仓库 GIT_DEPLOY_REPO: chuchu-z/chuchu-z.github.io # Hexo 编译后要部署到的分支 GIT_DEPLOY_BRANCH: master jobs: build: name: Build on node ${{ matrix.node_version }} and ${{ matrix.os }} # 配置运行的机器环境 runs-on: ubuntu-latest if: github.event.repository.owner.id == github.event.sender.id strategy: matrix: os: [ubuntu-latest] node_version: [14] # 执行步骤 steps: - name: Checkout uses: actions/checkout@v2 - name: Checkout deploy repo uses: actions/checkout@v2 with: repository: ${{ env.GIT_DEPLOY_REPO }} ref: ${{ env.GIT_DEPLOY_BRANCH }} path: .deploy_git - name: Use Node.js ${{ matrix.node_version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node_version }} # 授权密钥 - name: Configuration environment env: HEXO_DEPLOY_PRI: ${{secrets.HEXO_DEPLOY_PRI}} run: | sudo timedatectl set-timezone \"Asia/Shanghai\" mkdir -p ~/.ssh/ echo \"$HEXO_DEPLOY_PRI\" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts # coding 已取消同步 ssh-keyscan -t rsa e.coding.net >> ~/.ssh/known_hosts ssh-keyscan -t rsa gitee.com >> ~/.ssh/known_hosts git config --global user.name $GIT_USER git config --global user.email $GIT_EMAIL # 安装并执行hexo - name: Install dependencies run: | npm install -g hexo-cli --no-fund npm install -g --no-fund hexo clean hexo generate - name: Deploy hexo run: | npm run deploy 把配置文件提交到github仓库之后, 只要src(源代码)分支触发push操作,就会自动触发部署,在Actions就可以看到具体部署情况。 总结在学习了网上其他大佬们的方法后自己稍微做了些修改,也是总算成功完成了,感觉这次处理起来比上次使用travis-ci简单快的多,也可能是之前踩过不少坑了,这次比较顺利,早知道GitHub Actions这么方便就不用travis-ci了, 不过要不是travis-ci收费了我现在也还不知道GitHub Actions也挺好用,刚好天亮了睡觉😴。","categories":[{"name":"Other","slug":"other","permalink":"http://chuchu-z.com/categories/other/"}],"tags":[]},{"title":"gRPC的简介与Protobuf的使用","slug":"gRPC-info-and-Protobuf-use","date":"2023-02-13T19:36:50.000Z","updated":"2024-12-31T06:57:56.016Z","comments":true,"path":"posts/gRPC-info-and-Protobuf-use/","link":"","permalink":"http://chuchu-z.com/posts/gRPC-info-and-Protobuf-use/","excerpt":"gRPC实现微服务,将大的项目拆分为多个小且独立的业务模块;即服务;各服务之间使用高效的Protobuf协议进行RPC调用。 Protobuf 实际是一套类似Json或者XML的数据传输格式和规范,用于不同应用或进程之间进行通信时使用。通信时所传递的信息是通过Protobuf定义的message数据结构进行打包,然后编译成二进制的码流再进行传输或者存储。","text":"gRPC实现微服务,将大的项目拆分为多个小且独立的业务模块;即服务;各服务之间使用高效的Protobuf协议进行RPC调用。 Protobuf 实际是一套类似Json或者XML的数据传输格式和规范,用于不同应用或进程之间进行通信时使用。通信时所传递的信息是通过Protobuf定义的message数据结构进行打包,然后编译成二进制的码流再进行传输或者存储。 gRPC开发的核心文件是*.proto文件 ,它定义了gRPC服务和消息的约定。根据这个文件,gRPC框架可以通过protoc 工具生成服务基类,消息和完整的客户端代码, 支持 C++、Java、Go、Python、Ruby、C#、Node.js、Android Java、Objective-C、PHP等多种编程语言。 protoc 是用于将proto文件编程成各种语言源码文件的工具。 PHP使用gRPC安装扩展在PHP中使用gRPC需要先安装gRPC扩展和protobuf扩展 # 使用pecl安装 # 查看pecl版本 pecl version #如果没有安装 pecl # php版本 > 7 wget http://pear.php.net/go-pear.phar php go-pear.phar # php版本 < 7 yum install php-pear #否则会报错PHP Parse error: syntax error, unexpected //'new' (T_NEW) in /usr/share/pear/PEAR/Frontend.php on //line 91 # 查看版本 /usr/local/php/bin/pear version # 使用pecl安装grpc和protobuf /usr/local/php/bin/pecl install grpc /usr/local/php/bin/pecl install protobuf # 写入到php.ini配置(重启php生效) echo \"extension=grpc.so\" >> /usr/local/php/etc/php.ini echo \"extension=protobuf.so\" >> /usr/local/php/etc/php.ini php -m | grep grpc php -m | grep protobuf 安装protoc工具下载 protoc源码 具体版本要选择与proto文件中定义一致, 否则报错无法解析proto文件, 目前我们使用的是proto3, 所以我当前使用的protoc工具是3.10.1版本 # 先安装协议缓存编译器(否则解析proto文件生成对应代码时会乱码) yum install protobuf-compiler libtool libsysfs # 解压 tar -xvf protobuf-3.10.1.tar.gz # 编译安装 cd protobuf-3.10.1 ./autogen.sh ./configure # 如果报错 configure: WARNING: no configuration information is in third_party/googletest # 需要下载googletest,下载地址:https://github.com/google/googletest/releases # 直接解压并重命名googletest,放在 protobuf-3.10.1/third_party/googletest,然后重新执行./autogen.sh之后的 make make install # 查看protoc版本 protoc --version 使用protoc工具使用protoc工具, 生成PHP代码文件 # 执行命令 protoc --php_out=out_dir file.proto # --php_out 表示生成PHP代码格式 # out_dir 生成代码要存放的路径 # file.proto 要编译的proto文件 示例: protoc工具生成php代码1 protoc工具生成php代码2 aexlib(工作目录)中调用gRPC生成的代码放到aexlib/Lib/Plugin/ 目录下, 新建一个Api.php和Client.php, 编写具体的业务逻辑, 并在aexlib/Lib/Model/**下新建model**, model内调用Api.php具体方法","categories":[{"name":"Other","slug":"other","permalink":"http://chuchu-z.com/categories/other/"}],"tags":[]},{"title":"Linux Shell 使用alias定义别名","slug":"linux-shell-alias-config","date":"2022-03-31T01:57:18.000Z","updated":"2024-12-31T06:57:56.018Z","comments":true,"path":"posts/linux-shell-alias-config/","link":"","permalink":"http://chuchu-z.com/posts/linux-shell-alias-config/","excerpt":"在我们使用终端时, 为了提高平时工作效率和减少常用命令过长, 敲起来浪费时间, 可在/etc/profile文件中配置alias,自定指令的别名","text":"在我们使用终端时, 为了提高平时工作效率和减少常用命令过长, 敲起来浪费时间, 可在/etc/profile文件中配置alias,自定指令的别名 打开/etc/profile配置文件 vim /etc/profile 在文件末尾增加以下配置 #[alias] ##cd dir## alias -- -='cd -' # 此处意思为输入 - 回车, 相当于执行 cd -, 快速切换回上一个目录(两个目录之间来回切换) alias ..='cd ..' alias e='exit' alias 'www'='cd $www' # $www是个人配置的环境变量, $www指向的是工作目录 ##vim file## alias 'vp'='vim /etc/profile' alias 'vv'='vim /etc/vimrc' alias 'sp'='source /etc/profile' ##git## alias 'gs'='git status' alias 'gaa'='git add .' alias 'gcm'='git commit -m' alias 'gco'='git checkout' alias 'gb'='git branch -vvv' alias 'gd'='git diff' alias 'cls'='clear' alias -- --='git checkout -' #此处意思为输入 -- 回车, 相当于执行 git checkout -, 快速切换回上一个分支(两个分支之间来回切换) alias 'show'='git show' alias 'push'='git push origin `git branch --show-current`' alias 'fpush'='git push -f origin `git branch --show-current`' #强推 alias 'pull'='git pull origin `git branch --show-current`' alias 'rpull'='git pull origin `git branch --show-current` --rebase' #pull时增加 --rebase参数 alias 'ml'='git log --author=`git config user.name`' #查看本人提交的log alias 'gl'='git log' alias 'ggl'='git log --graph' alias 'gglp'='git log --graph --pretty=oneline --abbrev-commit' #可视化查看分支线的情况 alias 'review'='review() { git status --short | egrep ^*.php | sed \"s/^ *//\" | egrep ^[^D] | tr -s \" \"| cut -d\" \" -f 2 | egrep -v database/migrations | xargs $1;};review' #列出修改过未提交的php文件 alias 'qq'='review \"git checkout\"' #把列出修改过未提交的php文件当做参数 提供给git checkout, 全部撤销 ##ssh## alias 'chuchu'='ssh root@ip' ##Docker## alias 'dkre'='docker-compose restart' alias 'dkup'='docker-compose up' alias 'dkop'='docker-compose stop' alias 'dkphp'=\"winpty docker exec -it `docker ps --filter='name=php7' -q` bash\" #快速进入docker的php7容器 alias 'dkphp5'=\"winpty docker exec -it `docker ps --filter='name=php5' -q` bash\" 执行 source /etc/profile 重新加载刚修改配置生效 source /etc/profile","categories":[{"name":"Linux","slug":"linux","permalink":"http://chuchu-z.com/categories/linux/"}],"tags":[]},{"title":"Git 中的奇葩玩法","slug":"git-ridiculous-behavior","date":"2022-03-25T11:01:50.000Z","updated":"2024-12-31T06:57:56.016Z","comments":true,"path":"posts/git-ridiculous-behavior/","link":"","permalink":"http://chuchu-z.com/posts/git-ridiculous-behavior/","excerpt":"随机的 git commit 你敢提交吗 一个 Git 随机生成提交日志网站, 每次刷新的内容随机 太搞了, 不怕挨揍的壮士可以使用如下命令进行日常代码的提交😂","text":"随机的 git commit 你敢提交吗 一个 Git 随机生成提交日志网站, 每次刷新的内容随机 太搞了, 不怕挨揍的壮士可以使用如下命令进行日常代码的提交😂 git commit -m $(curl -s http://whatthecommit.com/index.txt) http://whatthecommit.com 没有最坑,只有更坑!此仓库专门收集史上最坑爹的代码片段,专治低血压 😁 https://gitee.com/oschina/bullshit-codes/tree/master","categories":[{"name":"Git","slug":"git","permalink":"http://chuchu-z.com/categories/git/"}],"tags":[]},{"title":"关于谷歌Chrome浏览器非安全端口限制问题","slug":"chrome-proxy-limit","date":"2022-03-24T04:38:16.000Z","updated":"2024-12-31T06:57:56.013Z","comments":true,"path":"posts/chrome-proxy-limit/","link":"","permalink":"http://chuchu-z.com/posts/chrome-proxy-limit/","excerpt":"关于前段时间深圳疫情严重, 公司选择通过VPN居家远程办公 有个项目在App端测试由于无法通过VPN请求Api, 运维开放了外网地址并指定端口","text":"关于前段时间深圳疫情严重, 公司选择通过VPN居家远程办公 有个项目在App端测试由于无法通过VPN请求Api, 运维开放了外网地址并指定端口 但在Chrome浏览器上打开时无法正常得到正常的响应, 而使用postman等测试工具是可以正常响应的 这个问题以前有遇到过,是因为 Chrome 浏览器对非安全端口进行了限制, 具体端口可在这里查看 https://chromium.googlesource.com/chromium/src.git/+/refs/heads/master/net/base/port_util.cc 解决的办法windows只需要右键Chrome浏览器快捷图标, 在属性设置里面的目标处增加以下参数, 然后关闭Chrome重新打开即可正常访问 # 多个端口号以英文逗号隔开 --explicitly-allowed-ports=10080,30300 Mac # Chrome浏览器的解决方案 open -a /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --explicitly-allowed-ports=6666,8888 Chrome 302重定向本以为解决完端口问题后就可以快乐地编码, 然而当我正常打开页面登录后, 又遇到了另一个问题 登录成功后, 只要点击其他任意跳转, 页面会被重定向跳回到登录界面, 初步判断是因为Cookies的问题, 导致登录态没有了 遗留问题1. 无法确定是因为端口的问题导致Cookies丢失 具体是事例在网上只找到了这个, 不确定是否同样的原因, 但因为我的Chrome浏览器版本目前是99.0.4844.82版本, 正如此博主所说 在chrome91及其以上版本,无法找到SameSite by default cookies和Cookies without SameSite must be secure两项配置 虽然没有解决我的问题, 但起码提供了参考 遗留问题2. 无法验证该方案是否可行","categories":[{"name":"Other","slug":"other","permalink":"http://chuchu-z.com/categories/other/"}],"tags":[]},{"title":"Win10 自定义 Git-Bash 终端界面 + 一言API与终端结合","slug":"windows10-git-bash","date":"2022-02-25T02:39:27.000Z","updated":"2024-12-31T06:57:56.022Z","comments":true,"path":"posts/windows10-git-bash/","link":"","permalink":"http://chuchu-z.com/posts/windows10-git-bash/","excerpt":"由于Git默认的界面长的实在是不够美观, 平时用起来都无法赏心悦目, 参考网上的一些文章资料, 做了下改动","text":"由于Git默认的界面长的实在是不够美观, 平时用起来都无法赏心悦目, 参考网上的一些文章资料, 做了下改动 修改Git Bash 窗口左上角标题#该命令是一次性的,关闭后重新打开会恢复, 后面有完整的 echo -ne \"\\\\e]0;title name\\\\a\" 修改命令提示符具体操作 打开 git-prompt.sh 文件 vim /etc/profile.d/git-prompt.sh 将其修改为如下内容: if test -f /etc/profile.d/git-sdk.sh then TITLEPREFIX=SDK-${MSYSTEM#MINGW} else TITLEPREFIX=$MSYSTEM fi if test -f ~/.config/git/git-prompt.sh then . ~/.config/git/git-prompt.sh else PS1='\\[\\033]0;Bash\\007\\]' # 窗口标题 PS1=\"$PS1\"'\\n' # 换行 PS1=\"$PS1\"'\\[\\033[32;1m\\]' # 高亮绿色 PS1=\"$PS1\"' ➜ ' # unicode 字符,右箭头, 如果显示不出来大概率是utf-8编码问题 PS1=\"$PS1\"'\\[\\033[33;1m\\]' # 高亮黄色 PS1=\"$PS1\"'\\W' # 当前目录 PS1=\"$PS1\"'\\[\\033[34;1m\\]' # 高亮蓝色 PS1=\"$PS1\"' [\\t]' # 当前时间 if test -z \"$WINELOADERNOEXEC\" then GIT_EXEC_PATH=\"$(git --exec-path 2>/dev/null)\" COMPLETION_PATH=\"${GIT_EXEC_PATH%/libexec/git-core}\" COMPLETION_PATH=\"${COMPLETION_PATH%/lib/git-core}\" COMPLETION_PATH=\"$COMPLETION_PATH/share/git/completion\" if test -f \"$COMPLETION_PATH/git-prompt.sh\" then . \"$COMPLETION_PATH/git-completion.bash\" . \"$COMPLETION_PATH/git-prompt.sh\" PS1=\"$PS1\"'\\[\\033[31m\\]' # 红色 PS1=\"$PS1\"'`__git_ps1`' # git 插件 fi fi PS1=\"$PS1\"'\\[\\033[36m\\] ' # 青色 fi MSYS2_PS1=\"$PS1\" 这个非常像 oh-my-zsh 的风格, 其实一开始就是想用zsh终端的, 奈何windows不支持, 如果平时日常开发想装的话也可以在linux虚拟主机或者docker里面装一个, zsh在目前来说可以说是最强大的shell了, 谁用谁知道 修改界面主题vim ~/.minttyrc 默认配置如下: Transparency=low Language= ForegroundColour=0,255,64 CursorColour=0,255,64 CursorType=block Scrollbar=none FontHeight=12 把以下内容添加到配置文件里面: Font=Fira Code Medium FontHeight=14 FontHeight=14 Transparency=low FontSmoothing=default Locale=C Charset=UTF-8 Columns=88 Rows=26 OpaqueWhenFocused=no Scrollbar=none Language=zh_CN ForegroundColour=131,148,150 BackgroundColour=0,43,54 CursorColour=220,130,71 BoldBlack=128,128,128 Red=255,64,40 BoldRed=255,128,64 Green=64,200,64 BoldGreen=64,255,64 Yellow=190,190,0 BoldYellow=255,255,64 Blue=0,128,255 BoldBlue=128,160,255 Magenta=211,54,130 BoldMagenta=255,128,255 Cyan=64,190,190 BoldCyan=128,255,255 White=200,200,200 BoldWhite=255,255,255 BellTaskbar=no Term=xterm FontWeight=400 FontIsBold=no 最后重启Git-Bash就可以看到配置好的界面了 效果图: image-20220225095728006 另外说一下第一行是在 Options 中选择字体时设置的,我使用了 Fira Code, 14号字体, Fira Code就是一款为写程序而生的字体 以上内容参考网络文章 有兴趣的可以深入了解这里, 不过也有可能无法访问了 Fira CodeFira 是 Mozilla 公司(火狐浏览器她爹)主推的字体系列。Fira Code 是其中的一员,专为写程序而生。出来具有等宽等基本属性外,还加入了编程连字特性(ligatures)。 Fira Code 就是利用这个特性对编程中的常用符号进行优化,比如把输入的「!=」直接显示成「≠」或者把「>=」变成「≥ 」等等,以此来提高代码的可读性 本人的使用的IDE也是装的这一款字体, 咳咳跑题了.. 一言与终端结合去年无意发现一个名叫 一言 的网站, 这个网站只是单纯的提供一句话, 可以是动漫中的台词,也可以是网络上的各种小段子。 或是感动,或是开心,有或是单纯的回忆 并且还官方还提供了 API接口文档 供我们免费调用, 于是并尝试了把该功能与终端做结合, 大概就是, 启动终端时请求API, 把随机返回的句子显示在终端上, 我认为是个有趣的想法, 具体实现思路, 写一个请求一言API的脚本, 终端启动时自动调用一次这个脚本 效果如下: 图片 编写一言脚本, 文件名和路径没有具体要求, 看个人 vim yy 具体代码GitHub上也有, 直接拿下面的也行: # 一言 # 返回普通文本 #`curl -ks https://v1.hitokoto.cn/?encode=text` url='https://v1.hitokoto.cn' if [ x$1 != x ]; then url='https://v1.hitokoto.cn?'$1 fi # 处理 json 数据(处理json数据需要安装jq) json=`curl -ks $url` # linux 安裝jq # yum install epel-release # yum list jq # yum install jq # windows 安裝jq # https://stedolan.github.io/jq/ random=$[RANDOM%7+31] echo -e content=`echo ${json} | jq '.hitokoto' | sed 's/\"//g' | tr -d '\\n'` printf \"\\033[1;${random}m%s\\033[0m\" \"『 \" $content \" 』\" from_who=`echo ${json} | jq '.from_who' | sed 's/\"//g' | tr -d '\\n'` echo -e if [ \"$from_who\" == 'null' ] then from_who='匿名' fi length=`expr ${#content} \\* 2` printf \"\\033[1;${random}m%${length}s\\033[0m\" \"—— $from_who\" from=`echo ${json} | jq '.from' | sed 's/\"//g' | tr -d '\\n'` printf \"\\033[1;${random}m%s\\033[0m\" \"「\" $from \"」\" echo -e exit 0 编写完后可以试着执行 yy脚本一下试试 (代码里有说明要安装jq处理json数据) 具体效果 最后编辑~/.bashrc文件, 因为Git-Bash启动时会加载此文件 vim ~/.bashrc 在文件内容里加上yy后保存退出重新启动Git-Bash就行, (我能直接执行yy是配置了环境变量的, 如果没有配置的话需要写绝对路径) # vim ~/.bashrc # Git-Bash 初始化加载此配置文件 # shopt -s expand_aliases # 允许shell脚本中使用 alias 命令 # 经测试, 在 #!/bin/sh 下, 该命令可有可无, 不影响 alias 的使用 # 在 !/bin/bash 下,才有影响 yy","categories":[{"name":"Git","slug":"git","permalink":"http://chuchu-z.com/categories/git/"}],"tags":[]},{"title":"一言网(hitokoto.cn)API接入shell脚本","slug":"hitokoto-api-shell","date":"2022-02-24T03:49:48.000Z","updated":"2024-12-31T06:57:56.017Z","comments":true,"path":"posts/hitokoto-api-shell/","link":"","permalink":"http://chuchu-z.com/posts/hitokoto-api-shell/","excerpt":"前言之前发现个很不错的网站 一言网(hitokoto.cn) 很喜欢该网站的提供的服务 并且他们还提供了免费的API接口, 只需要访问该接口, 就会返回一段话 https://v1.hitokoto.cn/?encode=text 于是我就更想把它做进我的shell终端里","text":"前言之前发现个很不错的网站 一言网(hitokoto.cn) 很喜欢该网站的提供的服务 并且他们还提供了免费的API接口, 只需要访问该接口, 就会返回一段话 https://v1.hitokoto.cn/?encode=text 于是我就更想把它做进我的shell终端里 接口文档 一言接口文档 https://developer.hitokoto.cn/sentence/ 具体脚本代码# 返回普通文本 #`curl -ks https://v1.hitokoto.cn/?encode=text` url='https://v1.hitokoto.cn' if [ x$1 != x ]; then url='https://v1.hitokoto.cn?'$1 fi # 处理 json 数据(处理json数据需要安装jq) json=`curl -ks $url` # linux 安裝jq # yum install epel-release # yum list jq # yum install jq # windows 安裝jq # https://stedolan.github.io/jq/ random=$[RANDOM%7+31] echo -e content=`echo ${json} | jq '.hitokoto' | sed 's/\"//g' | tr -d '\\n'` printf \"\\033[1;${random}m%s\\033[0m\" \"『 \" $content \" 』\" from_who=`echo ${json} | jq '.from_who' | sed 's/\"//g' | tr -d '\\n'` echo -e if [ \"$from_who\" == 'null' ] then from_who='匿名' fi length=`expr ${#content} \\* 2` printf \"\\033[1;${random}m%${length}s\\033[0m\" \"—— $from_who\" from=`echo ${json} | jq '.from' | sed 's/\"//g' | tr -d '\\n'` printf \"\\033[1;${random}m%s\\033[0m\" \"「\" $from \"」\" echo -e exit 0","categories":[{"name":"Linux","slug":"linux","permalink":"http://chuchu-z.com/categories/linux/"}],"tags":[]},{"title":"Docker环境初始化及安装php扩展","slug":"docker-init-php-extensions","date":"2021-12-30T06:53:42.000Z","updated":"2024-12-31T06:57:56.013Z","comments":true,"path":"posts/docker-init-php-extensions/","link":"","permalink":"http://chuchu-z.com/posts/docker-init-php-extensions/","excerpt":"这只是一段操作命令的过程, 没有任何值得学习的地方…😁","text":"这只是一段操作命令的过程, 没有任何值得学习的地方…😁 yum -y install vim vim /root/.bashrc # 设置alias alias e='exit' alias www='cd /home/www/task_server' # 写入设置utf8编码,否则乱码,设置好后先保存退出,并执行source /root/.bashrc生效,再设置PS1变量 export LANG=\"en_US.utf8\" # 设置完编码后这里先退出保存一次,先让编码生效, 然后再打开编辑 source /root/.bashrc # 设置PS1变量 export PS1=\"\\[\\033]0;Docker\\007\\]\\n\\[\\033[32;1m\\] ➜ \\[\\033[33;1m\\]\\W\\[\\033[34;1m\\] [\\t]\\[\\033[31m\\]\\[\\033[36m\\] \" # 保存退出 source /root/.bashrc # 新框架资产中心需要用到GRPC, Docker环境下安装GRPC # 查看版本 pecl version #如果没有安装 pecl # php版本 > 7 wget http://pear.php.net/go-pear.phar php go-pear.phar # php版本 < 7 yum install php-pear #否则会报错PHP Parse error: syntax error, unexpected //'new' (T_NEW) in /usr/share/pear/PEAR/Frontend.php on //line 91 # 安装 grpc pecl install grpc # 因为pecl没有加入PATH变量, 如果默认pecl PHP版本小于7.0 则可以使用一下路径方式或者把/usr/local/php/bin/加入PATH变量 /usr/local/php/bin/pecl install protobuf /usr/local/php/bin/pecl install grpc /usr/local/php/bin/pecl install apcu # GCC版本4.8编译报错, 升级版本到gcc 7.3 yum -y install centos-release-scl yum -y install devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-binutils scl enable devtoolset-7 bash echo \"source /opt/rh/devtoolset-7/enable\" >>/etc/profile # ssh证书问题 如果没有openssl文件夹先创建 wget http://curl.haxx.se/ca/cacert.pem && mv cacert.pem /usr/local/openssl/cert.pem # 写入配置 echo \"extension=grpc.so\" >> /usr/local/php/etc/php.ini echo \"extension=protobuf.so\" >> /usr/local/php/etc/php.ini echo \"extension=apcu.so\" >> /usr/local/php/etc/php.ini #重启Docker Docker 启动报错Docker.Core.Backend.BackendException: Error response from daemon: open \\\\.\\pipe\\docker_engine_linux: The system cannot find the file specified. 在win10 管理员身份打开cmd命令行提示符执行: Net stop com.docker.service Net start com.docker.service 以往安装时执行过的命令参考1 vp 2 php -m 3 e 4 logout 5 exit 6 exit 7 yum -y install vim 8 vim /root/.bashrc 9 source /root/.bashrc 10 vim /root/.bashrc 11 source /root/.bashrc 12 pecl version 13 wget http://pear.php.net/go-pear.phar 14 php go-pear.phar 15 wget http://pear.php.net/go-pear.phar 16 php go-pear.phar 17 yum install php-pear 18 pecl install grpc 19 /usr/local/php/bin/pecl install protobuf 20 /usr/local/php/bin/pecl install protobuf 21 /usr/local/php/bin/pecl install grpc 22 yum install php70w-devel 23 /usr/bin/phpize 24 which phpize 25 /usr/bin/phpize 26 yum install php-devel 27 php -v 28 yum install php70w-devel 29 /usr/bin/phpize 30 which php 31 cd /usr/local/bin/php 32 pwd 33 ll 34 /usr/local/php/bin/pecl install protobuf 35 /usr/local/php/bin/pecl install grpc 36 gcc --version 37 g++ --version 38 yum -y install centos-release-scl 39 yum -y install devtoolset-6-gcc devtoolset-6-gcc-c++ devtoolset-6-binutils 40 scl enable devtoolset-6 bash 41 yum install centos-release-scl scl-utils-build 42 yum list all --enablerepo='centos-sclo-rh' 43 yum install devtoolset-4-gcc.x86_64 devtoolset-4-gcc-c++.x86_64 devtoolset-4-gcc-gdb-plugin.x86_64 44 scl --list 或 scl -l 45 scl --list 46 gcc -v 47 php -m 48 e 49 /usr/local/php/bin/pecl install protobuf 50 /usr/local/php/bin/pecl channel-update pecl.php.net 51 /usr/local/php/bin/pecl install protobuf 52 e 53 pecl version 54 wget http://pear.php.net/go-pear.phar 55 php go-pear.phar 56 vim /etc/profile 57 vim ~/.bashrc 58 vim ~/.bashrc 59 source ~/.bashrc 60 gcc --version 61 g++ --version 62 /usr/local/php/bin/pecl install protobuf 63 wget http://curl.haxx.se/ca/cacert.pem && mv cacert.pem /usr/local/openssl/cert.pem 64 ll 65 /usr/local/php/bin/pecl install protobuf 66 /usr/local/php/bin/pecl install grpc 67 /usr/local/php/bin/pecl install grpc 68 /usr/local/php/bin/pecl install apcu 69 /usr/local/php/bin/pecl install apcu 70 wget http://curl.haxx.se/ca/cacert.pem && mv cacert.pem /usr/local/openssl/cert.pem 71 ll 72 cd /usr/local/openssl 73 cd /usr/local/ 74 mkdir openssl 75 cd - 76 mv cacert.pem /usr/local/openssl/cert.pem 77 /usr/local/php/bin/pecl install apcu 78 vim /usr/local/php/etc/php.ini 79 e 80 pecl install grpc 81 pecl channel-update pecl.php.net 82 pecl install grpc 83 yum -y install centos-release-scl 84 yum -y install devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-binutils 85 scl enable devtoolset-7 bash 86 e 87 www 88 php tinyBell.php 89 php tinyBell.php start 90 php tinyBell.php start 91 pwd 92 e","categories":[{"name":"Docker","slug":"docker","permalink":"http://chuchu-z.com/categories/docker/"}],"tags":[]}],"categories":[{"name":"Linux","slug":"linux","permalink":"http://chuchu-z.com/categories/linux/"},{"name":"Docker","slug":"linux/docker","permalink":"http://chuchu-z.com/categories/linux/docker/"},{"name":"Docker","slug":"docker","permalink":"http://chuchu-z.com/categories/docker/"},{"name":"MySQL","slug":"mysql","permalink":"http://chuchu-z.com/categories/mysql/"},{"name":"岁月杂感","slug":"岁月杂感","permalink":"http://chuchu-z.com/categories/%E5%B2%81%E6%9C%88%E6%9D%82%E6%84%9F/"},{"name":"Other","slug":"other","permalink":"http://chuchu-z.com/categories/other/"},{"name":"Python","slug":"python","permalink":"http://chuchu-z.com/categories/python/"},{"name":"ChatGPT","slug":"python/chatgpt","permalink":"http://chuchu-z.com/categories/python/chatgpt/"},{"name":"wiki","slug":"docker/wiki","permalink":"http://chuchu-z.com/categories/docker/wiki/"},{"name":"hyperf","slug":"docker/hyperf","permalink":"http://chuchu-z.com/categories/docker/hyperf/"},{"name":"RabbitMQ","slug":"rabbitmq","permalink":"http://chuchu-z.com/categories/rabbitmq/"},{"name":"Android","slug":"android","permalink":"http://chuchu-z.com/categories/android/"},{"name":"Git","slug":"git","permalink":"http://chuchu-z.com/categories/git/"}],"tags":[]}