2025-06-24 10:30:42
查看 Docker 版本
此命令会展示客户端和服务端的 Docker 版本信息,对于确保不同环境中 Docker 版本兼容性十分重要。比如在团队协作开发时,统一 Docker 版本能避免因版本差异导致的问题。
docker version
查看 Docker 系统信息
执行该命令后,会输出 Docker 的系统级详细信息,涵盖镜像数量、容器数量、存储驱动类型、资源限制等内容。通过这些信息,可对当前 Docker 运行环境有全面了解,方便进行性能调优和资源管理。
docker info
列出正在运行的容器
它会列出当前正在运行的容器,显示容器 ID、使用的镜像、启动时间、运行状态、端口映射等关键信息,有助于快速掌握正在运行的容器情况。
docker ps
列出所有容器(包括停止的)
相比
docker ps
,该命令会列出所有容器,不管是正在运行还是已经停止的,方便查找和管理历史容器。
docker ps -a
列出所有镜像
用于展示本地存储的所有 Docker 镜像,包括仓库源、标签、镜像 ID、创建时间和大小等信息,便于管理和清理本地镜像。
docker images
查看容器详细信息
将
<container>
替换为实际容器 ID 或名称,执行后会以 JSON 格式输出容器的详细信息,包括网络配置、挂载点、环境变量等,在排查容器问题时非常有用。
docker inspect <container>
查看镜像详细信息
把
<image>
换成具体镜像 ID 或名称,能获取镜像的详细构建信息、分层情况等,对了解镜像内部结构和构建过程很有帮助。
docker inspect <image>
查看 Docker 事件
该命令实时输出 Docker 运行时的各种事件,如容器的创建、启动、停止、删除,镜像的拉取、推送等,方便监控 Docker 系统的活动情况。
docker events
查看镜像历史
通过此命令,能查看指定镜像的构建历史,了解镜像从基础镜像开始,每一层的创建操作和大小变化,有助于分析镜像大小和优化镜像构建过程。
docker history <image>
查看容器资源使用情况
实时显示正在运行容器的 CPU、内存、网络、磁盘 I/O 等资源使用情况,对于监控容器性能和及时发现资源瓶颈意义重大。
docker stats
后台运行容器
-d
参数让容器在后台运行,<image>
为要使用的镜像名称或 ID,常用于启动一些不需要用户实时交互的服务类容器,如数据库容器。
docker run -d <image>
运行交互式容器
-it
参数表示以交互式终端方式运行容器,会进入容器的 Shell 环境,方便在容器内进行调试、配置等操作。例如在基于 Ubuntu 镜像的容器中安装软件包。
docker run -it <image> /bin/bash
停止正在运行的容器
<container>
为要停止的容器 ID 或名称,正常停止容器,容器内的应用程序会收到停止信号,有机会进行一些清理操作。
docker stop <container>
启动已停止的容器
用于重新启动一个已经停止的容器,让容器恢复到之前的运行状态。
docker start <container>
重启容器
先停止容器,再启动容器,可用于应用程序配置更新后,需要重启容器使新配置生效的场景。
docker restart <container>
强制停止容器
直接向容器发送 SIGKILL 信号,强制终止容器运行,适用于容器出现异常,无法正常停止的情况。
docker kill <container>
删除容器
移除指定的容器,在删除前,容器必须处于停止状态。若要删除正在运行的容器,可使用
docker rm -f <container>
,但这会强制停止并删除容器。
docker rm <container>
连接到正在运行的容器
连接到一个正在运行的容器的标准输入、输出和错误流,不过当多个用户同时使用
attach
时,可能会出现输入输出混乱的情况,所以更推荐使用docker exec
。
docker attach <container>
在容器中执行命令
在运行的容器内执行指定命令
<cmd>
,<container>
为容器 ID 或名称。例如在运行的 Nginx 容器中执行nginx -s reload
命令来重新加载配置。
docker exec <container> <cmd>
重命名容器
将容器从
<old - name>
重命名为<new - name>
,方便对容器进行更有意义的命名,提高管理效率。
docker rename <old - name> <new - name>
暂停容器
暂停容器内的所有进程,容器占用的资源会保持,但进程不再运行,常用于临时暂停某个容器的服务,又不想完全停止它。
docker pause <container>
恢复暂停的容器
让之前暂停的容器恢复运行,容器内的进程继续执行。
docker unpause <container>
更新容器配置
可用于更新容器的资源限制、重启策略等配置,例如通过
docker update --memory = "512m" <container>
为容器设置内存限制。
docker update <container>
导出容器为 tar 包
将指定容器的文件系统导出为一个 tar 包,
<file>
为导出的文件名,常用于容器数据备份或在不同环境中迁移容器。
docker export <container> > <file>
查看容器日志
输出容器内应用程序的标准输出和标准错误日志,通过这些日志能排查容器内应用程序的运行问题,如启动失败、运行时错误等。
docker logs <container>
阻塞等待容器退出
该命令会阻塞当前终端,直到指定容器退出,并返回容器的退出状态码,在脚本中可用于判断容器是否成功运行结束。
docker wait <container>
查看容器文件系统变化
显示容器文件系统相对于基础镜像的变化,包括新增、修改和删除的文件和目录,有助于了解容器内应用程序对文件系统的操作情况。
docker diff <container>
从容器中复制文件到宿主机
将容器
<container>
内的<path>
路径下的文件或目录复制到宿主机的<dest>
路径下,方便获取容器内生成的数据或配置文件。
docker cp <container>:<path> <dest>
将容器保存为镜像
基于当前容器的状态和更改,创建一个新的镜像
<image>
,常用于将经过配置和调试后的容器固化为可复用的镜像。
docker commit <container> <image>
将镜像推送到仓库
将本地镜像
<image>
推送到 Docker 仓库,前提是已经登录到相应的仓库,并且镜像名称符合仓库的命名规则。
docker push <image>
构建镜像
-t
参数为构建的镜像指定名称和标签,<path>
为 Dockerfile 所在路径。Docker 会根据 Dockerfile 中的指令构建镜像,这是自定义镜像的重要方式。
docker build -t <image> <path>
删除本地镜像
删除本地指定的镜像
<image>
,若镜像被多个容器使用,需先删除相关容器才能删除镜像。也可使用docker rmi -f <image>
强制删除镜像,但要谨慎操作,以免影响正在运行的容器。
docker rmi <image>
给镜像添加标签
为已有的镜像
<image>
添加一个新的标签<new - tag>
,方便对镜像进行版本管理或标记不同用途的镜像。
docker tag <image> <new - tag>
搜索镜像
在 Docker Hub 上搜索包含
<keyword>
的镜像,会列出镜像名称、描述、星级等信息,便于找到满足需求的基础镜像。
docker search <keyword>
拉取镜像
从 Docker 仓库下载指定镜像
<image>
到本地,如果不指定标签,默认拉取latest标签的镜像。
docker pull <image>
保存镜像为 tar 包
将指定镜像
<image>
保存为一个 tar 包<file>
,可用于在没有网络连接的环境中传输和加载镜像。
docker save -o <file> <image>
从 tar 包加载镜像
从之前保存的 tar 包
<file>
中加载镜像到本地 Docker 环境,与docker save
配合使用,实现镜像的备份和恢复。
docker load -i <file>
列出网络
显示当前 Docker 环境中的所有网络,包括网络 ID、名称、驱动类型等信息,便于管理和查看容器网络配置。
docker network ls
创建网络
创建一个新的网络
<network>
,可指定网络驱动类型(如bridge
、overlay
等)以及其他网络配置参数,以满足不同的网络需求。
docker network create <network>
删除网络
删除指定的网络
<network>
,删除前需确保没有容器连接到该网络。
docker network rm <network>
查看网络详细信息
输出指定网络
<network>
的详细信息,如子网、网关、DNS 配置等,帮助了解网络的具体设置和运行状态。
docker network inspect <network>
连接容器到网络
将正在运行的容器
<container>
连接到指定网络<network>
,使容器能够与该网络中的其他容器通信。
docker network connect <network> <container>
从网络断开容器连接
将容器
<container>
从指定网络<network>
中断开连接,容器将无法再通过该网络与其他容器通信。
docker network disconnect <network> <container>
列出卷
展示当前 Docker 环境中所有的卷,包括卷的名称、驱动类型等信息,方便管理和查看容器数据存储。
docker volume ls
创建卷
创建一个新的卷
<volume>
,用于在容器间共享数据或持久化容器数据,避免容器删除时数据丢失。
docker volume create <volume>
删除卷
删除指定的卷
<volume>
,删除前需确保没有容器在使用该卷。
docker volume rm <volume>
查看卷详细信息
输出指定卷
<volume>
的详细信息,如挂载点、容量限制等,有助于了解卷的配置和使用情况。
docker volume inspect <volume>
在容器中挂载卷
在启动容器时,将卷
<volume>
挂载到容器内的<container - path>
路径,实现容器与宿主机或其他容器之间的数据共享和持久化。例如docker run -v my - volume:/data nginx
将my - volume
卷挂载到 Nginx 容器的/data
目录。
docker run -v <volume>:<container - path> <image>
指定容器名称
使用
--name
参数为容器指定一个易于识别的名称<name>
,方便在后续管理中通过名称操作容器,而不是使用难以记忆的容器 ID。
docker run --name <name> <image>
映射端口
将宿主机的端口
<host - port>
映射到容器内的端口<container - port>
,使外部可以通过宿主机端口访问容器内的服务。比如docker run -p 8080:80 nginx
将 Nginx 容器的 80 端口映射到宿主机的 8080 端口。
docker run -p <host - port>:<container - port> <image>
设置环境变量
使用
-e
参数为容器设置环境变量<env - var>
,可以设置多个环境变量。例如docker run -e "DB_USER = root" -e "DB_PASSWORD = password" mysql
为 MySQL 容器设置数据库用户名和密码环境变量。
docker run -e <env - var> <image>
限制容器资源
限制CPU
通过
--cpus
参数限制容器使用的 CPU 核心数,<number>
为具体的 CPU 核心数,如0.5
表示使用半个 CPU 核心。
docker run --cpus = "<number>" <image>
限制内存
使用
--memory
参数设置容器可使用的最大内存,<size>
为内存大小,如512m
表示 512MB 内存。
docker run --memory = "<size>" <image>
设置容器重启策略
--restart
参数用于设置容器的重启策略<policy>
,常见策略有always
(总是重启)、on - failure
(容器以非零状态码退出时重启)、no
(从不重启,默认值)。例如docker run --restart = always nginx
确保 Nginx 容器在任何情况下都自动重启。
docker run --restart = <policy> <image>
安装 Docker Compose
不同操作系统安装方式略有不同,以 Linux 为例,可通过以下命令安装:
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker - compose - $(uname - s)-$(uname - m)" -o /usr/local/bin/docker - compose
sudo chmod +x /usr/local/bin/docker - compose
启动服务
在包含
docker - compose.yml
文件的目录下,执行:
docker - compose up
停止服务
停止并删除由
docker - compose.yml
文件定义的所有服务容器、网络等资源。
docker - compose down
重启服务
重启由
docker - compose.yml
文件定义的所有服务容器。
docker - compose restart
查看服务状态
显示当前由
docker - compose.yml
文件管理的服务容器的运行状态,包括容器 ID、名称、状态等信息。
docker - compose ps
构建镜像
根据
docker - compose.yml
文件中定义的服务,构建所需的镜像。如果镜像已经存在,会根据情况更新镜像。
docker - compose build
执行命令
在指定的服务容器
<service>
内执行命令<command>
,例如docker - compose exec web python manage.py migrate
在名为web
的服务容器内执行 Django 的数据库迁移命令。
docker - compose exec <service> <command>
初始化 Swarm 集群
在作为 Swarm 管理器的节点上执行,该命令会初始化一个新的 Swarm 集群,并输出加入集群的命令,用于其他节点加入该集群。
docker swarm init
加入 Swarm 集群
在需要加入集群的节点上,运行
docker swarm init
命令输出的加入指令,其中<token>
为集群认证令牌,<manager-ip>
是 Swarm 管理器的 IP 地址,<manager-port>
为对应的端口号,三者缺一不可。
docker swarm join --token <token> <manager-ip>:<manager-port>
2025-06-22 04:41:55
本教程基于Ubuntu Server 24.04.2系统进行部署演示,需要提前安装好Docker和Docker Compose,如果尚未安装Docker,请参阅Install | Docker Docs(https://docs.docker.com/engine/install/)。
Ollama 是一个开源的本地大语言模型运行框架。
核心功能:Ollama 专注于在本地机器上便捷部署和运行大型语言模型(LLM),支持多种操作系统,包括 macOS、Windows、Linux 以及通过 Docker 容器运行。
主要特点:它提供对模型量化的支持,可以显著降低显存要求,使得在普通家用计算机上运行大型模型成为可能。
多种预训练语言模型支持:Ollama 提供了多种开箱即用的预训练模型,包括常见的 GPT、BERT 等大型语言模型,用户可以轻松加载并使用这些模型进行文本生成、情感分析、问答等任务。
易于集成和使用:Ollama 提供了命令行工具(CLI)和 Python SDK,简化了与其他项目和服务的集成,开发者无需担心复杂的依赖或配置,可以快速将 Ollama 集成到现有的应用中。
本地部署与离线使用:Ollama 允许开发者在本地计算环境中运行模型,这意味着可以脱离对外部服务器的依赖,保证数据隐私,并且对于高并发的请求,离线部署能提供更低的延迟和更高的可控性。
支持模型微调与自定义:用户不仅可以使用 Ollama 提供的预训练模型,还可以在此基础上进行模型微调,根据自己的特定需求,开发者可以使用自己收集的数据对模型进行再训练,从而优化模型的性能和准确度。
性能优化:Ollama 关注性能,提供了高效的推理机制,支持批量处理,能够有效管理内存和计算资源,这让它在处理大规模数据时依然保持高效。
跨平台支持:Ollama 支持在多个操作系统上运行,包括 Windows、macOS 和 Linux,这样无论是开发者在本地环境调试,还是企业在生产环境部署,都能得到一致的体验。
开放源码与社区支持:Ollama 是一个开源项目,这意味着开发者可以查看源代码,进行修改和优化,也可以参与到项目的贡献中,此外,Ollama 有一个活跃的社区,开发者可以从中获取帮助并与其他人交流经验。
本地模型管理:Ollama 支持从官方模型库或自定义模型库拉取预训练模型,并在本地保存和加载,它支持各种流行的模型格式(如 ONNX、PyTorch、TensorFlow)。
高效推理:通过 GPU/CPU 的加速,Ollama 提供高效的模型推理,适合本地化应用或需要控制数据隐私的场景。
多种接口访问:Ollama 支持命令行(CLI)、HTTP 接口访问推理服务,并通过 OpenAI 客户端实现更广泛的集成。
环境变量配置:通过灵活的环境变量,用户可以自定义推理设备(GPU/CPU)、缓存路径、并发数、日志级别等。
RAGFlow 是一款基于深度文档理解构建的开源 RAG(Retrieval-Augmented Generation)引擎。RAGFlow 可以为各种规模的企业及个人提供一套精简的 RAG 工作流程,结合大语言模型(LLM)针对用户各类不同的复杂格式数据提供可靠的问答以及有理有据的引用。
高质量的文档提取:支持多种格式的文档,能确保准确地抽取信息,可处理 Word、幻灯片、Excel、文本、图像、扫描件、结构化数据、网页等多种数据源。
基于模板的切片模式:支持各类切片模式,可根据不同场景的需求灵活地对数据进行分割。
检索内容可视化与溯源:检索内容支持溯源,切片透明,提高了系统的可解释性和可信度,能减少模型幻觉,提供有根据的引用。
多数据源与模型对接:支持多种类型的数据源,适应各种数据环境,提高了系统的通用性;同时兼容不同的语言模型,满足多样化的应用需求。
提供便捷 API:便于集成到现有系统中,能有效提高开发效率。
多路召回与重排序:通过多路召回和融合重排序,提高了检索精度和相关性。
支持 Graph 定制工作流:可以实现复杂的智能交互和决策流程。
首先对文档进行摄取和预处理,接着生成嵌入向量,然后对用户查询进行编码,再检索相关文档,构建增强提示,最后生成响应并进行验证和处理。
在客户服务、问答系统、智能搜索、内容推荐等领域都有重要应用,例如在在线客服系统中,能利用用户的历史咨询记录、产品文档以及 FAQ 等数据,实时检索出关联度最高的信息,并生成自然、连贯的应答,提升客户满意度。
主要包含数据检索模块和生成模块。数据检索模块负责在海量数据中快速定位、收集与过滤结果信息;生成模块则基于检索结果,利用生成式模型生成高质量的应答或文本内容。
通过官方提供的命令进行安装。
curl -fsSL https://ollama.com/install.sh | sh
通过ollama --version
检查ollama是否成功安装。
在Ollama Model (https://ollama.com/search)中查看支持的模型,通过ollama pull
命令下载模型到本地。
# 拉取 qwen3:8b
ollama pull qwen3:8b
(可选)Ollama默认监听127.0.0.1
的接口,可通过systemd 服务配置来修改Ollama默认监听IP。
sudo nano /etc/systemd/system/ollama.service
增加以下配置,监听所有接口0.0.0.0可能暴露服务到公网,建议结合防火墙使用。
Environment="OLLAMA_HOST=0.0.0.0"
Environment="OLLAMA_ORIGINS=*"
CTRL + O
写入文件,然后回车,最后CTRL + X
离开。
最后重新加载配置并重启服务:
sudo systemctl daemon-reload
sudo systemctl restart ollama
README(https://github.com/infiniflow/ragflow/blob/main/docker/README.md)
克隆仓库。
git clone https://github.com/infiniflow/ragflow.git
通过cd
命令进入到 docker 文件夹。
cd ragflow/docker
更新 docker/.env 文件内的 RAGFLOW_IMAGE
变量,设置 RAGFLOW_IMAGE=infiniflow/ragflow:v0.19.1
来下载 RAGFlow 镜像的 v0.19.1 完整发行版。
vim .env
按i
键进入编辑模式,修改好上述的环境变量后,按esc
键退出编辑模式,随后输入:wq
表示写入并退出。
(可选)修改RAGFlow服务默认端口
默认HTTP是
80
端口HPPTS是443
端口。
vim docker-compose.yml
按i
键进入编辑模式,将宿主机的映射端口进行修改,按esc
键退出编辑模式,随后输入:wq
表示写入并退出。
使用docker compose命令运行。
docker compose -f docker-compose.yml up -d
启动并运行服务器后,检查服务器状态。
docker logs -f ragflow-server
以下输出确认系统成功启动
____ ___ ______ ______ __
/ __ \ / | / ____// ____// /____ _ __
/ /_/ // /| | / / __ / /_ / // __ \| | /| / /
/ _, _// ___ |/ /_/ // __/ / // /_/ /| |/ |/ /
/_/ |_|/_/ |_|\____//_/ /_/ \____/ |__/|__/
* Running on all addresses (0.0.0.0)
2025-06-16 14:38:12
修改IMEI可以搭配特殊的物联卡使用,部分极具性价比的物联卡是绑定厂家自己设备进行使用的,如果使用其他的设备就需要将IMEI修改成厂家设备一致的IMEI进行使用。
该教程仅适用于烽火一代(LG6121F)的RP0107及以下版本的固件使用。
固件降级教程请参考【FiberHome】烽火5G CPE系统固件本地升降级。
使用超级管理员账户登录烽火5G CPE的后台管理。
账号:superadmin
密码
RP0102~RP0106版本:F1ber@dm
RP0107~RP203版本:F1ber$dm
在左侧菜单栏中选择「移动网络」→「AT指令」。
输入AT指令,xxxxxxxxxxxxxx
替换成你需要修改的IMEI,返回OK
则表示成功。
AT+EGMR=1,7,\"xxxxxxxxxxxxxx\"
2025-05-31 10:21:12
本教程基于飞牛系统 fnOS 0.9.8 的 Docker Compose 功能进行搭建。目前该dreamacro/clash-premium
镜像暂时不支持自动更新订阅,自动更新订阅需要配合脚本进行自动更新。
Clash 是一款跨平台、基于规则的开源代理工具,主要用于科学上网、网络加速和隐私保护。它通过灵活的规则引擎和丰富的协议支持,帮助用户高效管理网络流量,绕过地域限制。
创建以下目录结构。
/clash
├── docker-compose.yml
└── data/config/
└── config.yaml # 主配置文件
创建并编辑config.yaml
文件,然后保存至./clash/data/config/
文件夹下。
一般情况下订阅链接复制到浏览器打开便是一个
xxxx.yaml
的配置文件,将其内容复制粘贴放至config.yaml
文件。
注意将external-controller
的127.0.0.1:9090
务必修改成0.0.0.0:9090
port: 7890
socks-port: 7891
redir-port: 7892
allow-lan: true
mode: Rule
log-level: silent
external-controller: '0.0.0.0:9090'
secret: "your_strong_password" # 与compose中SECRET一致
# 代理规则示例(替换为实际订阅)
#proxies:
# - name: "Proxy-Server"
# type: ss
# server: server-ip
# port: 443
# cipher: aes-256-gcm
# password: "password"
#proxy-groups:
# - name: PROXY
# type: select
# proxies:
# - Proxy-Server
#rules:
# - DOMAIN-SUFFIX,google.com,PROXY
# - GEOIP,CN,DIRECT
# - MATCH,PROXY
打开Docker管理器,选择「Compose」,点击右上角「新增项目」。
在创建项目窗口中填写「项目名称」和选择数据存放「路径」,然后选择「创建docker-compose.yml」,将下列代码根据自己实际情况修改后复制粘贴进去。
version: '3.8'
services:
# Clash 核心服务
clash:
image: dreamacro/clash-premium:latest # 使用 Premium 版支持高级功能
container_name: clash-proxy
restart: unless-stopped
ports:
- "7890:7890" # HTTP 代理端口
- "7891:7891" # SOCKS5 代理端口
- "9090:9090" # 控制端口
volumes:
- ./data/config:/root/.config/clash # 配置文件目录
environment:
- TZ=Asia/Shanghai
- EXTERNAL_CONTROLLER=0.0.0.0:9090 # 控制端口监听
- SECRET=your_strong_password # API 访问密钥
# Clash 控制面板
yacd:
image: haishanh/yacd:latest
container_name: clash-dashboard
restart: unless-stopped
ports:
- "8080:80" # 面板访问端口 http://<ip>:8080
environment:
- YACD_DEFAULT_BACKEND=http://clash:9090 # 通过服务名连接Clash
- YACD_AUTH=your_strong_password # 与SECRET一致
勾选「创建项目后立即启动」,最后点击「确定」。
等待构建完成,然后在浏览器中输入IP:Port
访问。
添加链接,进入管理后台。
进入后台查看「代理」,如能正常显示信息,则表示config.yaml
文件格式没有问题。
在「配置」中打开「Allow LAN」
以 Windows 11 为例,使用代理。「设置」→「网络和Internet」→「代理」
手动设置代理
尝试访问地域限制网站,如谷歌(https://www.google.com/)、YouTube(https://www.youtube.com/)等进行试验。
以单个 Docker容器 为例,使用代理。使用 DockerCompose 构建镜像时,可以在 DockerCompose 中设置代理环境变量。
version: "3.8"
services:
metatube:
image: metatube/metatube-server:latest
container_name: metatube
restart: always
ports:
- "28080:8080" # Web访问端口
environment:
TZ: Asia/Shanghai # 设置为中国时区
http_proxy: http://192.168.1.6:7890 # 容器内HTTP代理
https_proxy: http://192.168.1.6:7890 # 容器内HTTPS代理
no_proxy: localhost,127.0.0.1,.internal,clash,yacd # 代理排除列表
2025-05-27 21:48:14
基于青龙面板编写的iKuuu每日自动签到脚本,请提前安装好青龙面板
特性说明:
多账户支持:自动读取环境变量中的多个账户信息
智能域名更新:自动检测官网域名变更并更新脚本
备用域名切换:主域名不可用时自动尝试备用域名
异常处理:单个账户失败不影响其他账户执行
结果通知:通过青龙内置通知服务推送聚合签到结果
# -*- coding: utf-8 -*
'''
定时自定义
0 0 1 * * ? iKuuu.py
new Env('iKuuu签到');
'''
import requests
import re
import json
import os
import datetime
import urllib.parse
import sys
import time
from bs4 import BeautifulSoup
# 添加青龙脚本根目录到Python路径
QL_SCRIPTS_DIR = '/ql/scripts' # 青龙脚本默认目录
sys.path.append(QL_SCRIPTS_DIR)
# 添加notify可能存在的其他路径
POSSIBLE_PATHS = [
'/ql', # 青龙根目录
'/ql/data/scripts', # 新版青龙数据目录
'/ql/scripts/notify', # 自定义通知目录
os.path.dirname(__file__) # 当前脚本目录
]
for path in POSSIBLE_PATHS:
if os.path.exists(os.path.join(path, 'notify.py')):
sys.path.append(path)
break
try:
from notify import send
except ImportError:
print("⚠️ 无法加载通知模块,请检查路径配置")
send = lambda title, content: None # 创建空函数防止报错
# 初始域名
ikun_host = "ikuuu.one" # 自动更新于2025-04-29 13:08:20
backup_hosts = ["ikuuu.one", "ikuuu.pw", "ikuuu.me"] # 备用域名列表
def get_latest_ikun_host():
test_url = f"https://{ikun_host}/"
try:
response = requests.get(test_url, timeout=10)
if response.status_code == 200:
if "官网域名已更改" in response.text or "Domain deprecated" in response.text:
print("检测到域名变更通知,正在提取新域名...")
h2_matches = re.findall(r'<h2>.*?(?:域名|domain)[::]\s*([a-zA-Z0-9.-]+)</h2>', response.text)
if h2_matches:
return h2_matches[0]
js_matches = re.findall(r'https?://([a-zA-Z0-9.-]+)/auth/login', response.text)
if js_matches:
return js_matches[0]
fallback_match = re.search(r'(?:域名|domain)[::]\s*([a-zA-Z0-9.-]+)', response.text)
if fallback_match:
return fallback_match.group(1)
print("⚠️ 检测到域名变更但无法提取新域名")
return None
else:
print("✅ 当前域名正常")
return None
except Exception as e:
print(f"域名检测异常: {e}")
return None
def update_self_host(new_host):
script_path = os.path.abspath(__file__)
with open(script_path, "r", encoding="utf-8") as f:
lines = f.readlines()
updated = False
for i, line in enumerate(lines):
if line.strip().startswith("ikun_host = "):
lines[i] = f'ikun_host = "{new_host}" # 自动更新于{datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\n'
updated = True
break
if updated:
with open(script_path, "w", encoding="utf-8") as f:
f.writelines(lines)
print(f"✅ 脚本已更新至域名: {new_host}")
return True
else:
print("⚠️ 域名更新失败")
return False
def test_host_reachable(host):
try:
response = requests.get(f"https://{host}/", timeout=10)
return response.status_code == 200
except:
return False
def get_remaining_flow(cookies):
"""获取用户剩余流量信息"""
user_url = f'https://{ikun_host}/user'
try:
# 获取用户页面
user_page = requests.get(user_url, cookies=cookies, timeout=15)
if user_page.status_code != 200:
return "获取流量失败", "状态码: " + str(user_page.status_code)
# 使用BeautifulSoup解析HTML
soup = BeautifulSoup(user_page.text, 'html.parser')
# 查找包含剩余流量的卡片
flow_cards = soup.find_all('div', class_='card card-statistic-2')
for card in flow_cards:
h4_tag = card.find('h4')
if h4_tag and '剩余流量' in h4_tag.text:
# 查找流量数值
counter_span = card.find('span', class_='counter')
if counter_span:
flow_value = counter_span.text.strip()
# 查找流量单位
unit_text = ""
next_sibling = counter_span.next_sibling
if next_sibling:
unit_text = next_sibling.strip()
return flow_value, unit_text
# 如果没有找到,尝试其他方式
flow_div = soup.find('div', string='剩余流量')
if flow_div:
parent_div = flow_div.find_parent('div', class_='card-body')
if parent_div:
flow_text = parent_div.get_text(strip=True).replace('剩余流量', '')
return flow_text.split()[0], flow_text.split()[1] if len(flow_text.split()) > 1 else ""
return "未找到", "流量信息"
except Exception as e:
return "流量获取异常", str(e)
def ikuuu_signin(email, password):
params = {'email': email, 'passwd': password, 'code': ''}
login_url = f'https://{ikun_host}/auth/login'
try:
# 登录请求
login_res = requests.post(login_url, data=params, timeout=15)
if login_res.status_code != 200:
flow_value, flow_unit = "登录失败", "无法获取"
return False, f"登录失败(状态码{login_res.status_code})", flow_value, flow_unit
login_data = login_res.json()
if login_data.get('ret') != 1:
flow_value, flow_unit = "登录失败", "无法获取"
return False, f"登录失败:{login_data.get('msg', '未知错误')}", flow_value, flow_unit
# 获取用户剩余流量
cookies = login_res.cookies
flow_value, flow_unit = get_remaining_flow(cookies)
# 执行签到
checkin_res = requests.post(f'https://{ikun_host}/user/checkin', cookies=cookies, timeout=15)
if checkin_res.status_code != 200:
return False, f"签到失败(状态码{checkin_res.status_code})", flow_value, flow_unit
checkin_data = checkin_res.json()
if checkin_data.get('ret') == 1:
return True, f"成功 | {checkin_data.get('msg', '')}", flow_value, flow_unit
else:
return False, f"签到失败:{checkin_data.get('msg', '未知错误')}", flow_value, flow_unit
except json.JSONDecodeError:
return False, "响应解析失败", "未知", "未知"
except requests.exceptions.Timeout:
return False, "请求超时", "未知", "未知"
except Exception as e:
return False, f"请求异常:{str(e)}", "未知", "未知"
def send_qinglong_notification(results):
"""
使用青龙面板内置通知系统发送通知
需要青龙面板已配置通知渠道(如钉钉、企业微信等)
"""
title = "iKuuu签到通知"
# 构建消息内容
success_count = sum(1 for res in results if res['success'])
failure_count = len(results) - success_count
message = [
f"🔔 签到完成 | 成功:{success_count} 失败:{failure_count}",
"================================"
]
for index, res in enumerate(results, 1):
status = "✅ 成功" if res['success'] else "❌ 失败"
message.append(f"{index}. {res['email']}")
message.append(f" 状态:{status}")
message.append(f" 详情:{res['message']}")
message.append(f" 剩余流量:{res['flow_value']} {res['flow_unit']}")
message.append("--------------------------------")
# 添加统计信息
message.append("\n🕒 执行时间:" + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
try:
# 发送通知(青龙自动处理多通知渠道)
send(title, "\n".join(message))
print("✅ 通知已发送")
except Exception as e:
print(f"⚠️ 通知发送失败,请检查通知配置: {str(e)}")
if __name__ == "__main__":
# ==================== 域名更新逻辑 ====================
print(f"当前域名: {ikun_host}")
latest_host = get_latest_ikun_host()
if latest_host:
print(f"检测到新域名: {latest_host}")
if update_self_host(latest_host):
ikun_host = latest_host
# ==================== 域名可用性检查 ====================
if not test_host_reachable(ikun_host):
print("主域名不可用,尝试备用域名...")
found = False
for host in backup_hosts:
if test_host_reachable(host):
ikun_host = host
print(f"切换到备用域名: {ikun_host}")
found = True
break
if not found:
print("❌ 所有域名均不可用")
exit(1)
# ==================== 账户处理 ====================
accounts = []
account_str = os.getenv('IKUUU_ACCOUNTS')
if not account_str:
print("❌ 未找到环境变量 IKUUU_ACCOUNTS")
exit(1)
for line in account_str.strip().splitlines():
if ':' in line:
email, pwd = line.split(':', 1)
accounts.append((email.strip(), pwd.strip()))
else:
print(f"⚠️ 忽略无效账户行: {line}")
if not accounts:
print("❌ 未找到有效账户")
exit(1)
# ==================== 执行签到 ====================
results = []
for email, pwd in accounts:
print(f"\n处理账户: {email}")
success, msg, flow_value, flow_unit = ikuuu_signin(email, pwd)
results.append({
'email': email,
'success': success,
'message': msg,
'flow_value': flow_value,
'flow_unit': flow_unit
})
print(f"结果: {'成功' if success else '失败'} - {msg}")
print(f"剩余流量: {flow_value} {flow_unit}")
# 账户间延迟防止请求过快
time.sleep(1)
# ==================== 结果通知 ====================
print("\n正在发送通知...")
send_qinglong_notification(results)
# ==================== 本地结果输出 ====================
print("\n签到结果汇总:")
for res in results:
print(f"邮箱: {res['email']}")
print(f"状态: {'成功' if res['success'] else '失败'}")
print(f"详情: {res['message']}")
print(f"剩余流量: {res['flow_value']} {res['flow_unit']}\n{'-'*40}")
环境变量配置(青龙面板),在「环境变量」里创建IKUUU_ACCOUNTS
:多个账户用换行分隔,格式为 邮箱:密码
[email protected]:password1
[email protected]:password2
配置推送通知(青龙面板),在「配置文件」中的config.sh
中根据提示配置通知服务。
将上述代码复制保存到记事本,并且重命名为iKuuu.py
。
打开青龙面板后台,「脚本管理」→「+」→「本地文件」,将保存的iKuuu.py
上传后点击「确定」。
添加定时任务。「定时任务」→「创建任务」,可自定义「名称」,「命令/脚本」固定为task iKuuu.py,「定时类型」选择常规定时,「定时规则」填写0 0 1 * * ?(每天凌晨一点执行)。
通知示例:
iKuuu签到通知
🔔 签到完成 | 成功:1 失败:1
================================
1. [email protected]
状态:❌ 失败
详情:签到失败:您似乎已经签到过了...
剩余流量:59.14 GB
--------------------------------
2. [email protected]
状态:✅ 成功
详情:成功 | 你获得了 2582 MB流量
剩余流量:54.34 GB
--------------------------------
🕒 执行时间:2025-05-27 13:51:46
日志输出:
每个账户的执行结果会在控制台详细输出
最终汇总结果通过内置通知模块推送(根据自己需求进行配置)
2025-05-17 13:24:03
不能实例化:抽象类不能被实例化,它通常作为基类存在,为子类提供一套通用的接口和部分实现。
包含实现:抽象类可以包含具体的方法实现和抽象方法。抽象方法必须在子类中被重写。
单继承:一个类只能继承自一个抽象类(C#中不支持多重继承)。
当你希望提供一个通用的基类,该基类定义了一些子类共有的方法实现,并且还有一些方法需要由子类提供具体实现时,使用抽象类是一个不错的选择。
namespace App01
{
// 抽象的图形基类
public abstract class Shape
{
// 抽象方法:计算面积
public abstract double Area();
// 具体实现的方法:显示形状信息
public void Display()
{
Console.WriteLine("This is a shape.");
}
}
// 圆形类,继承自Shape
publicclass Circle : Shape
{
publicdouble Radius { get; set; }
// 重写抽象方法:计算圆的面积
public override double Area()
{
return Math.PI * Radius * Radius;
}
}
// 矩形类,继承自Shape
publicclass Rectangle : Shape
{
publicdouble Width { get; set; }
publicdouble Height { get; set; }
// 重写抽象方法:计算矩形的面积
public override double Area()
{
return Width * Height;
}
}
internal class Program
{
static void Main(string[] args)
{
Circle circle = new Circle();
circle.Radius = 5;
Console.WriteLine("The area of the circle is {0}.", circle.Area());
Rectangle rectangle = new Rectangle();
rectangle.Width = 4;
rectangle.Height = 6;
Console.WriteLine("The area of the rectangle is {0}.", rectangle.Area());
}
}
}
说明:
Shape
类是一个抽象类,包含一个抽象方法Area()
和一个具体方法Display()
。
Circle
和Rectangle
类继承自Shape
,并实现了Area()
方法。
namespace App02
{
// 抽象的动物基类
public abstract class Animal
{
// 抽象方法:发出叫声
public abstract void MakeSound();
// 具体方法:共同的行为
public void Sleep()
{
Console.WriteLine("The animal is sleeping.");
}
}
// 狗类,继承自Animal
publicclass Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Dog barks: Woof!");
}
}
// 猫类,继承自Animal
publicclass Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Cat meows: Meow!");
}
}
internal class Program
{
static void Main(string[] args)
{
// 创建Dog对象
Dog dog = new Dog();
// 调用Dog的共同行为
dog.Sleep();
// 调用Dog的叫声
dog.MakeSound();
// 创建Cat对象
Cat cat = new Cat();
// 调用Cat的共同行为
cat.Sleep();
// 调用Cat的叫声
cat.MakeSound();
}
}
}
说明:
Animal
类定义了共有的行为Sleep()
,并要求子类实现MakeSound()
方法。
完全抽象:接口只能包含方法、属性、事件、索引器的声明,不能包含任何实现。
多实现:一个类可以实现多个接口,实现接口即需要实现其所有成员。
成员默认是公共的:接口成员默认是公共的,不能包含访问修饰符。
当你希望定义一组不相关类之间的通用行为契约,并且不涉及实现细节时,接口是最好的选择。
namespace App01
{
// 可绘制的接口
public interface IDrawable
{
void Draw();
}
// 可变形的接口
public interface ITransformable
{
void Rotate(double angle);
void Scale(double factor);
}
// 实现了IDrawable和ITransformable的形状类
publicclass TransformableShape : IDrawable, ITransformable
{
public void Draw()
{
Console.WriteLine("Drawing the shape.");
}
public void Rotate(double angle)
{
Console.WriteLine($"Rotating the shape by {angle} degrees.");
}
public void Scale(double factor)
{
Console.WriteLine($"Scaling the shape by a factor of {factor}.");
}
}
internal class Program
{
static void Main(string[] args)
{
TransformableShape shape = new TransformableShape();
shape.Draw();
shape.Rotate(45);
shape.Scale(2.0);
Console.ReadKey();
}
}
}
说明:
IDrawable和ITransformable是两个接口,定义了绘制和变形的行为。
TransformableShape类实现了这两个接口,必须提供所有方法的实现。
namespace App02
{
// 数据存储接口
public interface IDataStore
{
void Save(string data);
string Load();
}
// 本地文件存储类
publicclass FileDataStore : IDataStore
{
public void Save(string data)
{
Console.WriteLine("Saving data to file.");
// 实际的文件保存逻辑
}
public string Load()
{
Console.WriteLine("Loading data from file.");
// 实际的文件加载逻辑
return"Data from file";
}
}
// 云端存储类
publicclass CloudDataStore : IDataStore
{
public void Save(string data)
{
Console.WriteLine("Saving data to cloud.");
// 实际的云保存逻辑
}
public string Load()
{
Console.WriteLine("Loading data from cloud.");
// 实际的云加载逻辑
return"Data from cloud";
}
}
internal class Program
{
static void Main(string[] args)
{
// 选择存储方式
IDataStore dataStore = new FileDataStore();
// 保存数据
dataStore.Save("Some data");
// 加载数据
string loadedData = dataStore.Load();
Console.WriteLine("Loaded data: " + loadedData);
}
}
}
有时,我们可以将抽象类和接口结合起来使用,以充分利用它们的优势。
namespace App03
{
// 抽象的动物类
public abstract class Animal
{
public abstract void Eat();
public void Breathe()
{
Console.WriteLine("Animal breathes.");
}
}
// 可移动的接口
public interface IMovable
{
void Move();
}
// 可飞行的接口
public interface IFlyable
{
void Fly();
}
// 狗类,继承自Animal并实现IMovable接口
publicclass Dog : Animal, IMovable
{
public override void Eat()
{
Console.WriteLine("Dog eats.");
}
public void Move()
{
Console.WriteLine("Dog runs.");
}
}
// 鸟类,继承自Animal并实现IMovable和IFlyable接口
publicclass Bird : Animal, IMovable, IFlyable
{
public override void Eat()
{
Console.WriteLine("Bird eats.");
}
public void Move()
{
Console.WriteLine("Bird walks.");
}
public void Fly()
{
Console.WriteLine("Bird flies.");
}
}
internal class Program
{
static void Main(string[] args)
{
// 创建Dog对象并调用方法
Dog dog = new Dog();
dog.Eat();
dog.Breathe();
dog.Move();
// 创建Bird对象并调用方法
Bird bird = new Bird();
bird.Eat();
bird.Breathe();
bird.Move();
bird.Fly();
Console.ReadKey();
}
}
}
说明:
Animal
是一个抽象类,定义了所有动物的共有行为。
IMovable
和IFlyable
是接口,定义了可移动和可飞行的行为。
Dog
类继承自Animal
并实现了IMovable
接口。
Bird
类继承自Animal
并实现了IMovable
和IFlyable
接口。
特性 |
抽象类 |
接口 |
---|---|---|
实例化 |
❌ 不能实例化 |
❌ 不能实例化 |
实现内容 |
✅ 可包含具体方法和抽象方法 |
❌ 仅声明成员,无实现 |
继承/实现数量 |
单继承(一个子类只能继承一个父类) |
多实现(一个类可实现多个接口) |
成员访问修饰符 |
支持(如 |
成员默认 |
字段/属性 |
✅ 可定义字段、属性 |
❌ 只能声明属性(无字段) |
设计目的 |
提供代码复用和部分通用逻辑 |
定义行为契约,实现多态 |
结合优势:抽象类提供基础实现,接口扩展额外功能。
示例:
Animal
抽象类定义Eat()
和Breathe()
。
IMovable
和IFlyable
接口分别定义移动和飞行能力。
Dog
继承Animal
并实现IMovable
。
Bird
继承Animal
并实现IMovable
和IFlyable
。
抽象类:聚焦于代码复用和层次化设计,适合“是什么”(Is-A)关系。
接口:聚焦于行为契约和功能扩展,适合“能做什么”(Can-Do)关系。
组合使用:通过抽象类提供基础能力,接口扩展多样化功能,实现灵活设计。