首页
关于道锋
友情链接
公告栏
麟图图床
麟云文件
麟云证书
BH5UVN
Search
1
使用ReDroid打造自己的云手机
5,065 阅读
2
Cloudflare SAAS 接入自选教程
2,774 阅读
3
CloudFront CDN配置教程
2,347 阅读
4
Frpc使用XTCP不通过服务器传输
2,206 阅读
5
兽装曲腿制作文档
2,205 阅读
默认
科学
热力学
Furry
小说
星河野望
手工制作
道具制作
音影
图像工具
计算机
渗透
硬件
编程
网络
记录
AI人工智能
CVE
软件工具
装机教程
C/C++
C#
Go
HTML5+JS+CSS
JAVA
Lua
Rust
PHP
Python2/3
Nodejs
编译
C/C++学习日志
Golang学习日志
Rust开发技巧
Rust学习日志
Rust开发教程
Nonebot2机器人框架
python开发教程
python开发技巧
Python学习日志
ai绘画
电子电路
电路设计
PCB打板
制作实战
无线电
摄影
运维
WEB
KVM云计算
docker
Ansible
代码管理
Kubernetes
Linux
MySQL
shell
集群
Zabbix
Prometheus
数据安全
Redis
istio
ELK
Nginx
Apache
Tomcat
Elasticsearch
Logstash
Kibana
测评
服务器
登录
Search
标签搜索
开源
源码
教程
服务器
环境搭建
摄影
rustlang
Rust
VS CODE
v2ray
bbr
加速
网络优化
拥塞控制
CloudFront教程
CF教程
AWS教程
CloudFront接入
Frpc
Frps
道锋潜鳞
累计撰写
447
篇文章
累计收到
129
条评论
首页
栏目
默认
科学
热力学
Furry
小说
星河野望
手工制作
道具制作
音影
图像工具
计算机
渗透
硬件
编程
网络
记录
AI人工智能
CVE
软件工具
装机教程
C/C++
C#
Go
HTML5+JS+CSS
JAVA
Lua
Rust
PHP
Python2/3
Nodejs
编译
C/C++学习日志
Golang学习日志
Rust开发技巧
Rust学习日志
Rust开发教程
Nonebot2机器人框架
python开发教程
python开发技巧
Python学习日志
ai绘画
电子电路
电路设计
PCB打板
制作实战
无线电
摄影
运维
WEB
KVM云计算
docker
Ansible
代码管理
Kubernetes
Linux
MySQL
shell
集群
Zabbix
Prometheus
数据安全
Redis
istio
ELK
Nginx
Apache
Tomcat
Elasticsearch
Logstash
Kibana
测评
服务器
页面
关于道锋
友情链接
公告栏
友人
iMin博客
特资啦!个人资源分享站
三石的记录
咬一口激动的鱼
中二病晚期の物語
奇梦博客
布丁の小窝
道麟笔记
迷失的小K
koto's Site
西西のBlog
锐冰龙小站
Nick的琐碎日常
渣渣120
猎空のBlog“
Suntの小破站
BG5VXJ-无线电
Abyss博客
麟图图床
麟云文件
麟云证书
BH5UVN
搜索到
38
篇与
的结果
2025-07-11
Ollama离线部署
在当前AI浪潮中,越来越多的企业希望在内网环境中部署自己的大语言模型,既要享受AI带来的效率提升,又要确保数据安全和合规性。Ollama作为一个轻量级的大模型运行平台,为离线部署提供了极佳的解决方案。本文将详细介绍Ollama的离线部署实践,从环境准备到模型运行的完整流程。Ollama架构解析与优势Ollama的设计哲学是"简单而强大"。它将复杂的大模型推理过程封装成简洁的命令行工具,同时提供了灵活的API接口。其核心优势在于对GGUF格式模型的原生支持,这种格式经过量化优化,能够在有限的硬件资源上高效运行大模型。Ollama的架构采用了客户端-服务端分离的设计。服务端负责模型的加载、推理和资源管理,客户端提供用户交互界面。这种架构的好处是可以在一台服务器上运行多个模型实例,多个客户端可以同时访问,实现资源的高效利用。在离线环境中,Ollama的另一个重要优势是其模块化的设计。核心运行时、模型文件、配置文件都是独立的组件,可以分别下载和部署,这为离线安装提供了极大的便利。离线部署环境准备离线部署的第一步是准备完整的安装包。与在线安装不同,离线部署需要预先下载所有必要的组件。核心组件下载# 下载Ollama主程序(在有网络的机器上执行) wget https://ollama.com/download/ollama-linux-amd64 # 下载安装脚本 curl -fsSL https://ollama.com/install.sh -o install.sh这里需要特别注意的是,Ollama的安装脚本默认会从网络下载程序文件,但在离线环境中我们需要修改脚本逻辑,让它使用本地已下载的文件。安装脚本改造安装脚本的改造是离线部署的关键技术点。原始脚本中的网络下载逻辑需要被替换为本地文件复制:# 找到脚本中的下载命令(大约在第XX行) # 原始代码: # curl --fail --show-error --location --progress-bar \ # -o $TEMP_DIR/ollama "https://ollama.com/download/ollama-linux-${ARCH}${VER_PARAM}" # 替换为: cp ./ollama-linux-amd64 $TEMP_DIR/ollama这种改造的核心思想是保持安装脚本的其他逻辑不变(如用户创建、权限设置、系统服务配置等),只修改文件获取的方式。这样可以确保离线安装后的系统状态与在线安装完全一致。模型文件获取策略大模型文件是整个部署过程中最大的挑战,不仅因为文件体积庞大,还因为需要选择合适的模型格式和版本。模型源选择国内用户可以优先选择ModelScope作为模型下载源,它提供了丰富的中文优化模型,下载速度也相对稳定:# ModelScope模型下载示例 # 访问 https://modelscope.cn/models # 搜索目标模型,如 Qwen2.5-7B-Instruct # 下载对应的GGUF格式文件对于需要最新国际模型的用户,HuggingFace仍然是首选,但需要考虑网络访问的问题。GGUF格式的技术优势GGUF(GPT-Generated Unified Format)是当前大模型量化的标准格式,相比原始的FP16或FP32模型,它具有以下技术优势:内存效率:通过INT4、INT8等低精度量化,大幅减少内存占用,使得消费级硬件也能运行大模型。加载速度:优化的文件格式结构,支持内存映射和增量加载,显著提升模型启动速度。推理性能:针对现代CPU和GPU的SIMD指令集进行了优化,在保持精度的同时提升推理速度。Modelfile配置深度解析Modelfile是Ollama的核心配置文件,它定义了模型的行为、参数和提示模板。深入理解Modelfile的各个部分对于定制化部署至关重要。核心指令解析FROM ./codeqwen-1_5-7b-chat-q8_0.gguf TEMPLATE """{{ if .System }}<|im_start|>system {{ .System }}<|im_end|> {{ end }}{{ if .Prompt }}<|im_start|>user {{ .Prompt }}<|im_end|> {{ end }}<|im_start|>assistant {{ .Response }}<|im_end|> """ PARAMETER stop "<|im_start|>" PARAMETER stop "<|im_end|>" PARAMETER temperature 0.7 PARAMETER top_p 0.8FROM指令是模型文件的引用,支持本地路径、URL或已存在的模型名称。在离线部署中,使用相对路径引用本地GGUF文件是最常见的方式。TEMPLATE指令定义了对话模板,这是模型理解对话上下文的关键。不同的模型家族有不同的对话格式,如ChatML、Alpaca、Vicuna等。正确配置对话模板直接影响模型的响应质量。PARAMETER指令用于调整模型的生成参数。temperature控制创意性(0-2,越高越有创意),top_p控制词汇选择的多样性(0-1,越高越多样),stop定义停止词用于控制生成的边界。高级配置技巧对于企业级部署,还可以配置更多高级参数:PARAMETER num_ctx 4096 # 上下文长度 PARAMETER num_predict 256 # 最大生成长度 PARAMETER repeat_penalty 1.1 # 重复惩罚 PARAMETER mirostat 2 # Mirostat采样算法 PARAMETER mirostat_tau 5.0 # Mirostat目标困惑度这些参数的调整需要根据具体的应用场景和性能要求来确定。比如,代码生成任务可能需要更高的num_ctx来处理长代码文件,而创意写作可能需要适当提高temperature。模型创建与管理模型创建是将GGUF文件和Modelfile组合成可运行模型的过程。这个过程涉及模型索引建立、配置验证、资源预分配等多个步骤。创建流程详解# 创建工作目录 sudo mkdir -p /opt/llm/models cd /opt/llm/models # 上传模型文件和配置文件 # - codeqwen-1_5-7b-chat-q8_0.gguf # - modelfile-codeqwen.Modelfile # 执行模型创建 ollama create codeqwen:7b -f ./modelfile-codeqwen.Modelfile创建过程中,Ollama会进行以下操作:文件验证:检查GGUF文件的完整性和格式正确性配置解析:解析Modelfile中的各项配置索引建立:为模型建立内部索引,优化后续加载速度依赖检查:验证系统资源是否满足模型运行要求模型版本管理在企业环境中,通常需要管理多个模型版本。Ollama支持语义化版本管理:# 创建不同版本的模型 ollama create codeqwen:7b-v1.0 -f ./modelfile-v1.Modelfile ollama create codeqwen:7b-v1.1 -f ./modelfile-v1.1.Modelfile # 设置默认版本(latest标签) ollama create codeqwen:latest -f ./modelfile-latest.Modelfile这种版本管理策略让模型的升级和回滚变得简单可控,特别适合需要频繁更新模型的场景。运行时优化与性能调优模型的运行性能直接影响用户体验,特别是在资源受限的环境中。Ollama提供了多种优化手段来提升性能。内存管理优化# 设置环境变量优化内存使用 export OLLAMA_NUM_PARALLEL=2 # 并行请求数量 export OLLAMA_MAX_LOADED_MODELS=1 # 最大加载模型数 export OLLAMA_FLASH_ATTENTION=1 # 启用Flash AttentionOLLAMA_NUM_PARALLEL控制同时处理的请求数量。在内存充足的情况下,可以适当增加这个值来提高并发处理能力。但需要注意的是,每增加一个并行请求,内存消耗会相应增加。OLLAMA_MAX_LOADED_MODELS限制同时加载到内存中的模型数量。对于单模型服务,设置为1可以确保所有内存资源都用于当前模型。OLLAMA_FLASH_ATTENTION启用Flash Attention算法,这是一种内存高效的注意力机制实现,可以显著减少内存占用并提升计算速度。GPU加速配置对于配备GPU的服务器,可以启用GPU加速来大幅提升推理速度:# 检查GPU可用性 ollama run --help | grep gpu # 设置GPU内存分配 export OLLAMA_GPU_MEMORY_FRACTION=0.8 # 启用混合精度计算 export OLLAMA_GPU_PRECISION=fp16GPU加速的效果通常非常显著,特别是对于大参数模型。但需要注意的是,不是所有的量化模型都能完全利用GPU加速,需要根据具体的模型格式和硬件配置来调整。服务化部署与高可用在生产环境中,通常需要将Ollama部署为系统服务,确保高可用性和稳定性。系统服务配置# 创建服务配置文件 sudo tee /etc/systemd/system/ollama.service > /dev/null <<EOF [Unit] Description=Ollama Service After=network-online.target [Service] ExecStart=/usr/local/bin/ollama serve User=ollama Group=ollama Restart=always RestartSec=3 Environment="OLLAMA_HOST=0.0.0.0:11434" Environment="OLLAMA_MODELS=/usr/share/ollama/.ollama/models" [Install] WantedBy=default.target EOF # 启用并启动服务 sudo systemctl daemon-reload sudo systemctl enable ollama sudo systemctl start ollama这个服务配置实现了以下功能:自动重启:Restart=always确保服务异常退出后自动重启,RestartSec=3设置重启间隔为3秒,避免频繁重启。网络绑定:OLLAMA_HOST=0.0.0.0:11434让服务监听所有网络接口,方便远程访问。权限隔离:使用专用的ollama用户运行服务,提高安全性。负载均衡与集群部署对于高并发场景,可以部署多个Ollama实例并配置负载均衡:# Nginx负载均衡配置 upstream ollama_backend { server 192.168.1.10:11434 weight=1; server 192.168.1.11:11434 weight=1; server 192.168.1.12:11434 weight=1; } server { listen 80; location /api/ { proxy_pass http://ollama_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_buffering off; } }这种部署方式可以实现水平扩展,通过增加节点来提高整体处理能力。模型迁移与备份策略在企业环境中,模型的迁移和备份是必须考虑的问题。Ollama的模型文件存储在特定目录中,可以通过文件系统操作来实现迁移。模型文件结构/usr/share/ollama/.ollama/ ├── models/ │ ├── manifests/ │ ├── blobs/ │ └── locks/ └── history/manifests目录存储模型的元数据信息,包括模型配置、版本信息等。blobs目录存储实际的模型文件数据,采用了内容寻址的存储方式,相同的数据块只存储一份。locks目录用于并发访问控制,确保模型文件在加载过程中不被修改。迁移操作实践# 源服务器导出模型 sudo tar -czf ollama-models-backup.tar.gz -C /usr/share/ollama .ollama/ # 目标服务器导入模型 sudo systemctl stop ollama sudo rm -rf /usr/share/ollama/.ollama/ sudo tar -xzf ollama-models-backup.tar.gz -C /usr/share/ollama/ sudo chown -R ollama:ollama /usr/share/ollama/.ollama/ sudo systemctl start ollama这种迁移方式可以完整保留所有模型数据和配置,确保迁移后的功能完全一致。API集成与开发接口Ollama提供了REST API接口,便于与其他应用系统集成。API的设计遵循了RESTful规范,使用JSON格式进行数据交换。核心API接口# 模型推理接口 curl -X POST http://localhost:11434/api/generate \ -H "Content-Type: application/json" \ -d '{ "model": "codeqwen:7b", "prompt": "写一个快速排序算法", "stream": false }' # 对话接口 curl -X POST http://localhost:11434/api/chat \ -H "Content-Type: application/json" \ -d '{ "model": "codeqwen:7b", "messages": [ {"role": "user", "content": "解释一下机器学习的基本概念"} ] }'流式响应:通过设置"stream": true,可以实现流式响应,用户可以实时看到生成过程,提升交互体验。上下文管理:对话接口支持多轮对话,通过维护消息历史来保持上下文连贯性。错误处理与监控在生产环境中,需要实现完善的错误处理和监控机制:import requests import time import logging def ollama_chat(prompt, model="codeqwen:7b", max_retries=3): for attempt in range(max_retries): try: response = requests.post( "http://localhost:11434/api/generate", json={ "model": model, "prompt": prompt, "stream": False }, timeout=60 ) response.raise_for_status() return response.json()["response"] except requests.exceptions.Timeout: logging.warning(f"Request timeout, attempt {attempt + 1}") except requests.exceptions.RequestException as e: logging.error(f"Request failed: {e}") if attempt < max_retries - 1: time.sleep(2 ** attempt) # 指数退避 raise Exception("All retry attempts failed")安全加固与访问控制在企业环境中部署大模型服务,安全性是首要考虑因素。需要从网络访问、用户权限、数据保护等多个维度进行安全加固。网络安全配置# 配置防火墙规则 sudo ufw allow from 192.168.1.0/24 to any port 11434 sudo ufw deny 11434 # 配置反向代理认证 # 在Nginx中添加基本认证 auth_basic "Ollama API"; auth_basic_user_file /etc/nginx/.htpasswd;通过限制网络访问范围和添加认证机制,可以防止未授权访问。模型访问权限控制虽然Ollama本身不提供细粒度的权限控制,但可以通过中间件来实现:# API网关示例 from flask import Flask, request, jsonify import requests app = Flask(__name__) # 用户权限配置 USER_PERMISSIONS = { "user1": ["codeqwen:7b"], "user2": ["codeqwen:7b", "qwen:14b"], "admin": ["*"] } @app.route("/api/generate", methods=["POST"]) def proxy_generate(): # 验证用户身份 api_key = request.headers.get("Authorization") user = validate_api_key(api_key) if not user: return jsonify({"error": "Unauthorized"}), 401 # 检查模型权限 data = request.json model = data.get("model") if not check_model_permission(user, model): return jsonify({"error": "Model access denied"}), 403 # 转发请求到Ollama response = requests.post( "http://localhost:11434/api/generate", json=data ) return response.json()性能监控与运维生产环境中的Ollama服务需要持续的监控和运维。关键指标包括响应时间、内存使用、GPU利用率、错误率等。监控指标收集# 创建监控脚本 cat > /opt/ollama/monitor.sh << 'EOF' #!/bin/bash while true; do # 内存使用率 memory_usage=$(ps -p $(pgrep ollama) -o %mem --no-headers) # GPU使用率(如果有GPU) gpu_usage=$(nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits) # 服务状态检查 if curl -s http://localhost:11434/api/version > /dev/null; then service_status="UP" else service_status="DOWN" fi # 记录到日志 echo "$(date): Memory=${memory_usage}%, GPU=${gpu_usage}%, Status=${service_status}" >> /var/log/ollama-monitor.log sleep 60 done EOF chmod +x /opt/ollama/monitor.sh日志管理# 配置日志轮转 cat > /etc/logrotate.d/ollama << 'EOF' /var/log/ollama*.log { daily rotate 30 compress delaycompress missingok notifempty create 644 ollama ollama postrotate systemctl reload ollama endscript } EOF故障排除与常见问题在实际部署过程中,可能会遇到各种问题。建立完善的故障排除流程可以快速定位和解决问题。常见问题诊断模型加载失败:通常是内存不足或GGUF文件损坏导致。可以通过ollama logs查看详细错误信息。响应速度慢:可能是模型参数设置不当或硬件资源不足。可以调整num_ctx、num_predict等参数优化性能。服务无法启动:检查端口占用、用户权限、文件路径等基本配置。调试工具使用# 查看服务日志 sudo journalctl -u ollama -f # 检查模型状态 ollama list # 测试API连通性 curl http://localhost:11434/api/version # 查看资源使用情况 htop nvidia-smi # 如果有GPU总结与最佳实践Ollama的离线部署虽然涉及多个技术环节,但通过系统化的方法和最佳实践,可以构建稳定、高效的企业级大模型服务。关键在于充分理解每个组件的作用和配置方法,结合实际需求进行优化调整。最佳实践建议:环境标准化:建立标准的部署脚本和配置模板,确保多环境部署的一致性。资源规划:根据预期负载合理配置硬件资源,特别是内存和存储空间。安全优先:从设计阶段就考虑安全因素,实现多层次的安全防护。监控完善:建立全面的监控体系,及时发现和处理潜在问题。文档维护:保持部署文档和操作手册的更新,便于团队协作和问题排查。随着大模型技术的不断发展,Ollama这样的轻量级部署工具将在企业AI应用中发挥越来越重要的作用。掌握其离线部署技术,对于构建自主可控的AI服务具有重要意义。
2025年07月11日
64 阅读
0 评论
0 点赞
2024-02-15
Linux下使用tcpdump监听DNS查询
Linux下使用tcpdump监听DNS查询 并解决docker connection reset by peer问题
2024年02月15日
248 阅读
0 评论
0 点赞
2024-01-13
使用ReDroid打造自己的云手机
前言市面上已经存在很多云手机厂商如红手指、多多云、雷电云、河马云手机等,价格从几十到上百元每月一台。价格还好说,但设备运行稳定性、可靠性、数据安全性全部依赖第三方厂商,注定不能进行敏感性操作或部署对安全可靠高要求的企业级服务。本文介绍一种开源的 AIC (Android In Container) 解决方案 ReDroid,使用本教程可以在一台普通型服务器运行多个安卓设备环境,并可在客户机电脑连接使用该云手机。Redroid介绍redroid(Remote an Droid)是一个 GPU 加速的 AIC(Android In Cloud)解决方案。Docker您可以在 Linux 主机( 、podman等)中启动多个实例k8s。redroid支持arm64和amd64架构。 redroid适用于云游戏、虚拟化电话、自动化测试等。目前支持:安卓 14 ( redroid/redroid:14.0.0-latest)仅适用于 Android 14 64 位 ( redroid/redroid:14.0.0_64only-latest)安卓 13 ( redroid/redroid:13.0.0-latest)仅适用于 Android 13 64 位 ( redroid/redroid:13.0.0_64only-latest)安卓 12 ( redroid/redroid:12.0.0-latest)仅适用于 Android 12 64 位 ( redroid/redroid:12.0.0_64only-latest)安卓 11 ( redroid/redroid:11.0.0-latest)安卓 10 ( redroid/redroid:10.0.0-latest)安卓 9 ( redroid/redroid:9.0.0-latest)安卓 8.1 ( redroid/redroid:8.1.0-latest)入门redroid 应该能够在任何 Linux 上运行(启用一些内核功能)。这里以使用阿里云的X86服务器进行演示,具体如下:配置:vCPUs2内存2G储存40G系统ubuntu-22.04架构x86-64带宽3M安装Docker## 安装 docker https://docs.docker.com/engine/install/#server # 根据 Docker 官方文档安装Docker curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh #或者从仓库下载 sudo apt update sudo apt-get install -y docker.io systemctl start docker systemctl enable docker 安装内核扩展模块更具不同的系统,有不一样的安装方法,具体如下 # 拉取内核模块源码 git clone https://github.com/remote-android/redroid-modules cd ./redroid-modules # Ubuntu 16.04 / 18.04 / 20.04 sudo apt-get install -y git kmod make gcc linux-headers-`uname -r` sudo make # build kernel modules sudo make install # build and install *unsigned* kernel modules # Ubuntu 20.04+ (kernel 5.0+) sudo modprobe ashmem_linux sudo modprobe binder_linux devices=binder,hwbinder,vndbinder # AmazonLinux2 git checkout origin/amazonlinux2 sudo yum install git kmod make "kernel-devel-uname-r == `uname -r`" sudo make # build kernel modules sudo make install # build and install *unsigned* kernel modules # Alibaba Cloud Linux 2 git checkout origin/alibabalinux2 sudo yum install git kmod make "kernel-devel-uname-r == `uname -r`" sudo make # build kernel modules sudo make install # build and install *unsigned* kernel modules # Alibaba Cloud Linux 3 git checkout origin/alibabalinux3 sudo yum install git kmod make "kernel-devel-uname-r == `uname -r`" sudo make # build kernel modules sudo make install # build and install *unsigned* kernel modules # openEuler 20.03 / kernel 4.19 git checkout origin/openeuler2003 sudo yum install gcc kernel-devel sudo KDIR=/usr/src/kernels/<VER> make install # 检查模块状态 lsmod | grep -e ashmem_linux -e binder_linux # example output: # binder_linux 147456 79 # ashmem_linux 16384 23 # 也可以这样验证 grep binder /proc/filesystems # output should like: nodev binder grep ashmem /proc/misc # output should like: 56 ashmem我这边因为是ubuntu 22.04,便使用 modprobe 安装如果不想换系统,可以尝试升级内核到5.0以上,默认就自带相关模块了启动容器创建Docker-compose文件docker-compose.ymlversion: "3" services: redroid: image: redroid/redroid:11.0.0-latest stdin_open: true tty: true privileged: true ports: - "20055:5555" volumes: # 資料存放在目前目錄下 - ./redroid-11-data:/data command: # 設定libndk相關 - ro.product.cpu.abilist0=x86_64,arm64-v8a,x86,armeabi-v7a,armeabi - ro.product.cpu.abilist64=x86_64,arm64-v8a - ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi - ro.dalvik.vm.isa.arm=x86 - ro.dalvik.vm.isa.arm64=x86_64 - ro.enable.native.bridge.exec=1 - ro.dalvik.vm.native.bridge=libndk_translation.so - ro.ndk_translation.version=0.2.2 - ro.secure=0 cap_add: - CAP_SYS_MODULE 启动容器#确保安装了docker-compose apt install docker-compose # 进入储存docker-compose.yml的目录 cd /data/redroid-1 docker-compose up -d如果使用 22.04可能出现如下异常解决方案pip install 'urllib3<2'链接根据 Scrcpy 官方文档下载安卓投屏软件源码包到客户机,解压使用adb connect ip:5555 # adb devices 可查看连接设备列表 scrcpy --serial ip:5555高级一些额外参数样例docker run -itd --rm --privileged \ --pull always \ -v ~/data:/data \ --cap-add CAP_SYS_MODULE \ -p 5555:5555 \ redroid/redroid:11.0.0-latest \ androidboot.redroid_width=1080 \ androidboot.redroid_height=1920 \ androidboot.redroid_dpi=480 \参数描述默认androidboot.redroid_width显示宽度720androidboot.redroid_height显示高度1280androidboot.redroid_fps显示 FPS30(启用 GPU) 15(未启用 GPU)androidboot.redroid_dpi显示 DPI320androidboot.use_memfd使用 memfd 替换已弃用的 ashmem计划默认启用假androidboot.use_redroid_overlayfs使用overlayfs共享data分区/data-base:共享data分区/data-diff:私有数据0androidboot.redroid_net_ndnsDNS 服务器数量,如果未指定 DNS 服务器,将使用“8.8.8.8”0androidboot.redroid_net_dns<1..N>域名解析 androidboot.redroid_net_proxy_type代理类型;从以下选项中选择:“静态”、“pac”、“无”、“未分配” androidboot.redroid_net_proxy_host androidboot.redroid_net_proxy_port 3128androidboot.redroid_net_proxy_exclude_list逗号分隔列表 androidboot.redroid_net_proxy_pac androidboot.redroid_gpu_mode从以下选项中选择:auto、host、guest;guest:使用软件渲染;host:使用 GPU 加速渲染;auto:自动检测自动androidboot.redroid_gpu_node 自动检测ro.xxxDEBUG 目的,允许覆盖 ro.xxx 属性;例如设置ro.secure=0,则默认提供root adb shell
2024年01月13日
5,065 阅读
2 评论
3 点赞
2023-08-11
D-Link Go-RT-AC750命令注入漏洞复现
D-Link Go-RT-AC750命令注入漏洞复现
2023年08月11日
356 阅读
0 评论
0 点赞
2023-07-17
使用CloudFlare Worker搭建Vless服务,实现无服务器代理
使用CloudFlare Worker搭建Vless服务,实现无服务器代理
2023年07月17日
999 阅读
0 评论
2 点赞
2023-04-04
ESP32 开发笔记: GPIO 参考指南
ESP32 开发笔记: GPIO 参考指南
2023年04月04日
173 阅读
0 评论
0 点赞
2023-02-25
在FastApi中运行Asyncio子进程导致NotImplementedError错误的解决方法
在FastApi中运行Asyncio子进程导致NotImplementedError错误的解决方法
2023年02月25日
363 阅读
1 评论
0 点赞
2022-07-23
Linux下du命令和df命令读取的磁盘占用不一致问题
前引前几天,站长随手打开了本站的后台,宝塔面板有接近一个月没有登陆控制面板,寻思着日志占用应该也非常大了然后站长就看到了如下场景50G的系统盘占用达到了69%(其实之前是85%,后来清理日志文件后降低到69%)然后发现不管怎么清理日志或者是其他的垃圾文件,空间占用就是没法降低。因此习惯性的连上sshdf -hl结果和宝塔显示的大同小异同样也是占用69%ps:这其实很正常,宝塔面板和df命令读取的都是磁盘的superblock信息,数据相同也无可厚非。但是问题就在这来了,站长不信邪,不相信系统盘占用有这么高。因为本站的服务器挂载有两块数据盘,一块800G,一块4T,站点日志和站点数据,面板都安装在数据盘上,理论上不应该会占用系统盘的空间啊。于是使用cd / du -sh * | sort -n du -h -x --max-depth=1去直接计算根目录下所有目录的大小好家伙,除去挂载点的大小,实际系统根目录占用仅仅5.5G,根本不到69%这是什么情况呢解决错误的想法细心的网友可能会注意到,如果这5.5G,加上www挂载点的15G,加上data挂载点的0.7G5.5+15+0.7,大概21.2G左右,加上前面的tmpfs空间,正好大概33G事情会不会这么巧呢,还真是巧合而已。解析区别前面有说,宝塔面板和df命令读取的都是磁盘分区的 superblock 信息。而 du 命令则是一个个调用系统的 fstat 去统计文件的总大小所以,理论上 df 统计的是更准确的那这么说,为什么 df 统计的结果会和 du 差那么多呢。是因为 df 统计的时候是从文件系统考虑的,不仅仅计算了文件的大小,也计算了被删除的文件,但进程还没释放的部分。例如文件已经被删除,但是被某个进程持有。其原理是读取每个分区的superblock来获取空闲数据块、已使用数据块.从而计算出空闲空间和已使用空间,所以也因此导致df统计的速度极快(才占用1024字节)。那df是怎么统计删除的文件的呢 简单说一下,只要bmap中不将这个文件的data block标记为未使用,就会算到实际使用的空间中。bmap是元数据区的一个位标记,其中记录的是数据区的block是否被使用。解决那我被占用的空间去哪了这是个好问题,但是在这之前,站长需要发一个提醒{message type="error" content="以下内容仅限在测试环境中使用测试,若应用于生产环境请三思后行"/}{message type="error" content="以下部分操作会杀死驻留进程,会影响到业务稳定,若需要使用,请按照具体情况进行修改"/}1.要找到这些丢失的空间,我们得首先先找到这些僵尸文件使用cd / lsof |grep deleted可以找到已经被表为deleted的文件被什么进程占用然后可以使用kill批量结束进程。cd / lsof |grep -i delete|awk '{print $2}'|xargs kill到这,基本上就能解决大部分问题了站长的系统盘占用也恢复了
2022年07月23日
356 阅读
1 评论
1 点赞
2022-04-17
境外服务器的各种线路说明
通过一篇短文带你了解AS4809,AS4134,AS4837,AS9929,CUVIP,AS9809,CN2,GIA,GT等各种网络线路,让你挑选服务器的时候,能够更加得心应手
2022年04月17日
379 阅读
0 评论
0 点赞
2022-04-06
Frpc使用XTCP不通过服务器传输
frp 是一个高性能的反向代理应用,可以帮助您轻松地进行内网穿透,对外网提供服务,支持 tcp, http, https 等协议类型,并且 web 服务支持根据域名进行路由转发。frp 是一款跨平台的内网穿透工具,支持 Windows、macOS 与 Linux,它需要你有一台拥有固定公网 IP 的电脑,VPS 最好,然后就能愉快的进行内网穿透了。还支持 https,甚至可以用它进行小程序开发。
2022年04月06日
2,206 阅读
1 评论
1 点赞
2021-02-04
支付宝五福自动脚本
源代码都给了,凑合着看吧源码来自一个不愿意透露姓名的开源人士,应要求将封面头图设为他头像使用方法:首先输入要领取的站点开始的序号,总共53个站点可以领取每隔77s会自动切换到下个站点进行领取,已经领取成功的,会进行记录,下次程序运行时将忽略领取成功的站点如果要换手机号领取,在一开始输入1确认,会自动把success.json覆盖掉,不然会因为上个手机号领取成功的站点而进行跳过。注意:支付宝此活动不能连续获得60(2月3日,根据大家的情况反映,支付宝已经把风控数量调整到10个验证码左右,24小时后解除风控)个验证码,否则24小时内无法再参加此次活动!程序暂无GUI页面,先凑合着用把。site.json、default.json和success.json必须和程序在一个目录,否则程序会闪退因为此次支付宝五福为了让大家交换卡,每人获得除了敬业福之外的随机两种福的概率是最大的,所以一般会大量开出两种福,这是正常现象。主要代码:import requests import os import codecs import sys import time import json import re from shutil import copyfile class WebRequests: def __init__(self): self.dirPath = '' self.getCaptchaUrl = 'https://rds.alipay.com/captcha.htm' self.getResultUrl = 'https://mobilegw.alipay.com/mgw.htm' self.operationType = { 'sendVerifyCode': 'alipay.tradecsa.biz.blessingprod.wufu2021.sendVerifyCode', 'outPrize': 'alipay.tradecsa.biz.blessingprod.wufu2021.outPrize' } self.s = requests.Session() self.headers = { 'User-Agent': 'Mozilla/5.0 (Linux; U; Android 10; zh-CN; MI 9 Build/QKQ1.190828.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 Quark/4.3.3.145 Mobile Safari/537.36 Edg/89.0.4389.6', 'DNT': '1' } def loads_jsonp(self, _jsonp): try: return json.loads(re.match(".*?({.*}).*", _jsonp, re.S).group(1)) except: raise ValueError('Invalid Input') def getCaptcha(self, mobile, source): digits = 32 hex = codecs.encode(os.urandom(digits), 'hex').decode() data = { 'appid': "blessingprod_wufu_otp", 'bizNo': hex, 'mobile': mobile, 'refer': "", 'scene': "DO_NOTHING", 'type': "silence", 'useragent': "Mozilla/5.0 (Linux; U; Android 10; zh-CN; MI 8 UD Build/QKQ1.190828.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 Quark/4.3.3.145 Mobile Safari/537.36 Edg/89.0.4389.6" } self.s.options(self.getCaptchaUrl) try: r = self.s.post(self.getCaptchaUrl, json=data, headers=self.headers) # print(r.text) rdsToken = json.loads(r.content)['data']['extra']['token'] requestData = [{"mobile": mobile, "source": source, "rdsBizNo": hex, "rdsToken": rdsToken}] getResultData = { '_fli_online': True, 'operationType': self.operationType['sendVerifyCode'], 'requestData': str(requestData), '_': int(round(time.time() * 1000)), 'callback': 'jsonp' + str(int(round(time.time() * 1000))) } re = self.s.get(self.getResultUrl, params=getResultData, headers=self.headers) # 'jsonp16121({"resultStatus":1000,"result":{"code":"5101","resultView":"人气太旺了,请稍后再试","success":true}})' # print(re.text) re_json = self.loads_jsonp(re.text) if re_json['result']['success'] == True: return {"code": 1000, "info": f'成功获取验证码,请注意查收'} else: resultView = re_json['result']['resultView'] return {"code": 1001, "info": f'获取验证码失败,原因为{resultView}'} except Exception as e: return {"code": 1001, "info": f'获取验证码失败,原因为 {e}'} def getResult(self, mobile, source, ackCode): requestData = [ {"mobile": mobile, "source": source, "ackCode": str(ackCode)}] getResultData = { '_fli_online': True, 'operationType': self.operationType['outPrize'], 'requestData': str(requestData), '_': int(round(time.time() * 1000)), 'callback': 'jsonp' + str(int(round(time.time() * 1000))) } try: re = self.s.get(self.getResultUrl, params=getResultData, headers=self.headers) # jsonp16121({"resultStatus":1000,"result":{"code":"50144","hasPrized":false,"hasUserId":false,"resultView":"已经领取过奖品","success":false}}) # print(re.text) re_json = self.loads_jsonp(re.text) if re_json['result']['success'] == True: return {"code": 1000, "info": f'成功领取'} else: resultView = re_json['result']['resultView'] return {"code": 1001, "info": f'领取失败,原因为 {resultView}'} except Exception as e: return {"code": 1001, "info": f'领取失败,原因为 {e}'} def getSiteNum(self): path = os.path.join(self.dirPath, "site.json") with open(path, 'r', encoding='utf8')as fp: json_data = json.load(fp) return len(json_data['channelList']) def getSiteInfo(self, num): path = os.path.join(self.dirPath, "site.json") with open(path, 'r', encoding='utf8')as fp: json_data = json.load(fp) length = len(json_data['channelList']) if num > length: print(f"站点的长度为{length},{num}已经超出这个长度") return None return json_data['channelList'][num-1] def getAllSiteInfo(self): path = os.path.join(self.dirPath, "site.json") with open(path, 'r', encoding='utf8')as fp: json_data = json.load(fp) return json_data['channelList'] def getSiteName(self, siteInfo): return siteInfo['sourceList'][0]['name'] def getSiteSource(self, siteInfo): return siteInfo['sourceList'][0]['source'] def addSuccessSite(self, siteInfo): path = os.path.join(self.dirPath, "success.json") add = self.isSuccessSite(siteInfo) if add == False: with open(path, 'r+', encoding='utf8')as fp: json_data = json.load(fp) with open(path, 'w', encoding='utf8')as fp: json_data['channelList'].append(siteInfo) fp.write(json.dumps(json_data, indent=4)) def isSuccessSite(self, siteInfo): path = os.path.join(self.dirPath, "success.json") with open(path, 'r+', encoding='utf8')as fp: json_data = json.load(fp) if siteInfo in list(json_data['channelList']): return True else: return False def main(path): webRequests = WebRequests() webRequests.dirPath = path print(f"总共有{webRequests.getSiteNum()}个站点可以领取福卡") for i in range(1, webRequests.getSiteNum()+1): siteInfo = webRequests.getSiteInfo(i) siteName = webRequests.getSiteName(siteInfo) print(f"{i}:{siteName}") startSite = int(input("您要从第几个站点开始向后领取?")) mobile = input("请输入您的手机号:") for i in range(startSite, webRequests.getSiteNum()+1): siteInfo = webRequests.getSiteInfo(i) siteName = webRequests.getSiteName(siteInfo) siteSource = webRequests.getSiteSource(siteInfo) if webRequests.isSuccessSite(siteInfo): print(f"{i}:{siteName} 已经成功领取,跳过") continue print(f"{i}:{siteName} 正在领取中") result = webRequests.getCaptcha(mobile, siteSource) print(result['info']) if result['code'] == 1001: if str(result['info']).find("验证码发送过频繁") != -1: print("验证码需等待77s后才能获取,正在等待..") time.sleep(77) result = webRequests.getCaptcha(mobile, siteSource) if str(result['info']).find("人气太旺啦,稍候再试试") != -1: print("您的手机号在近期已经获得了多次支付宝验证码,已被支付宝限制,24小时内无法再获得验证码,程序终止。") break elif str(result['info']).find("人气太旺啦,稍候再试试") == -1 and str(result['info']).find("验证码发送过频繁") == -1: continue ackCode = input("请输入验证码:") result = webRequests.getResult(mobile, siteSource, ackCode) print(result['info']) if result['code'] == 1000 or result['info'].find("已经领取过奖品") != -1: webRequests.addSuccessSite(siteInfo) print("验证码需等待77s后才能获取,正在等待..") time.sleep(77) input("程序已结束,您可以关闭此程序了") def newphone(): pa = 'success.json' if os.path.exists(pa): os.remove(pa) try: copyfile("default.json", pa) except IOError as e: print("错误 %s 5秒后退出" % e) time.sleep(5) sys.exit() except: print("错误,5秒后退出:", sys.exc_info()) time.sleep(5) sys.exit() if __name__ == '__main__': print("请问是否使用的新账号是输入1 否任意:") if int(input())== 1: newphone() path = os.path.dirname(os.path.realpath(sys.argv[0])) main(path) 源码地址:需要环境源码版:下载无需环境编译版:下载
2021年02月04日
157 阅读
2 评论
0 点赞
2020-11-15
对《奇迹觉醒》的解包研究学习
《奇迹MU:觉醒》是经韩国网禅正版授权,由北京天马时空网络技术有限公司研发,腾讯独家代理运营的一款手机游戏一、软件准备《apktool》1、apktool文件的下载apktool是反编译Android apk文件的工具,apktool的主页是 https://ibotpeaches.github.io/Apktool/;我们可以从这里找到最新版本的apktool.jar文件 https://bitbucket.org/iBotPeaches/apktool/downloads/,以及apktool的安装说明。2、apktool的安装前面我们已经下载了最新的apktool.jar文件,最新版本是2.3.1,请按照以下步骤操作,参考 https://ibotpeaches.github.io/Apktool/install/新建文本文件,将下面的脚本复制到文本并保存,然后重命名为apktool.bat;@echo off if "%PATH_BASE%" == "" set PATH_BASE=%PATH% set PATH=%CD%;%PATH_BASE%; chcp 65001 2>nul >nul java -jar -Duser.language=en -Dfile.encoding=UTF8 "%~dp0\apktool.jar" %* 从上面脚本中也可以看到是用apktool.jar文件去处理;将下载的apktool_2.3.1.jar文件重命名为apktool.jar;3、apktool的使用将上述两个文件apktool.bat和apktool.jar文件放到同一文件夹下(任意路径),打开命令窗口(win+R–>cmd–>enter);定位到apktool所在的文件夹;(若有java的系统变量也是可以的)输入以下命令:apktool.bat d -f ***.apk objectFolderPath 其中,objectFolderPath为可选项,如果此项不存在,软件将会在apktool文件夹下新建一个apk文件名的文件夹,否则存储到目标文件夹《UnityStudio》1.下载运行地址:https://github.com/Perfare/UnityStudio/releases最新版本支持unity5.x《winhex》(可选)下载地址http://www.x-ways.net/winhex.zip二、过程1.使用apktool对目标apk安装包进行拆解cd F:\解包\qjjx apktool d 10040714_com.tencent.tmgp.tmsk.qj2_a951663_8.2.0_27fhqs.apk //我的环境已经配置好了环境变量,直接cd到目标目录使用即可解包完成,目录下生成了一个和文件包同名的文件夹观察目录,发现asset文件夹占据了几乎99%的大小,估算模型数据在此目录下其实好像都是这个目录腾讯的开发者还是素质很高的,每个目录下是什么都清清楚楚的2.搜寻读取资源文件经过查看装备Equip,发现大量的unity3d文件(以此为例)还是打开winhex确认一下使用的版本号也是5.x使用先前下载的UnityStudio(或称AssetStudio)批量打开文件目录或单独打开文件比如。。。。资源的内容已经展示出来了(不限于此目录),可以选择需要的资源文件导出三、总结该文,该教材仅仅用作个人学习研究使用,请勿利用教材内容,进行有损目标软件公司利益的事情(包括但不限于版权纠纷,非法入侵纠纷)。本教程慨不负责类似案例:https://www.silverdragon.cn/?p=1880 过程几乎相同,且适用于几乎所有unity3D引擎的游戏
2020年11月15日
253 阅读
0 评论
0 点赞
1
2
...
4