文章以1pancel为例1.docker搭建esphome[collapse title="点击展开代码" status="false"]services: esphome: container_name: esphome image: ghcr.io/esphome/esphome volumes: - /opt/1panel/apps/local/esphome/esphome/config:/config - /etc/localtime:/etc/localtime:ro restart: always privileged: true network_mode: host environment: - USERNAME=admin - PASSWORD=feichangchang - TZ=Asia/Shanghai # ✨ 新增这行，强制指定容器时区为北京时间 [/collapse]2.root下创建esphome_panel.py和esphome_index.html2.1 编辑esphome_panel.py[collapse title="代码超长点击展开代码" status="false"]import os import re import time import subprocess from datetime import datetime from flask import Flask, render_template, request, jsonify, Response # 🎯 自动兼容：让 Flask 优先在当前脚本所在目录、当前目录的 templates 文件夹或 /root 下寻找网页 app = Flask(__name__, template_folder='.') # 🎯 你的真实 1Panel 挂载宿主机路径 CONFIG_DIR = "/opt/1panel/apps/local/esphome/esphome/config" LOG_FILE = os.path.join(CONFIG_DIR, "esphome_compile.log") # 全局编译状态锁 compile_status = {"status": "idle", "message": "Waiting..."} # 缓存上一次的 CPU 时间和网络数据，用于精准差值计算 sys_cache = { "last_cpu_time": None, "last_net_time": time.time(), "last_rx": 0, "last_tx": 0 } def get_esphome_device_name(yaml_path): try: with open(yaml_path, 'r', encoding='utf-8', errors='ignore') as f: content = f.read() match = re.search(r'name:\s*"?([a-zA-Z0-9_-]+)"?', content) if match: return match.group(1) except: pass return None def get_esphome_docker_version(): try: res = subprocess.run("docker exec esphome esphome version", shell=True, capture_output=True, text=True) match = re.search(r'Version:\s*([0-9.]+)', res.stdout) if match: return match.group(1) except: pass return "Unknown" def load_links_file(): links_file = os.path.join(CONFIG_DIR, "device_links.txt") links = {} if os.path.exists(links_file): try: with open(links_file, 'r', encoding='utf-8') as f: for line in f: if ',' in line: k, v = line.strip().split(',', 1) links[k] = v except: pass return links def save_links_file(links): links_file = os.path.join(CONFIG_DIR, "device_links.txt") try: with open(links_file, 'w', encoding='utf-8') as f: for k, v in links.items(): f.write(f"{k},{v}\n") except: pass def is_valid_esphome_yaml(filename): if filename.startswith('.') or filename in ['secrets.yaml', 'secrets.yml']: return False return filename.endswith('.yaml') or filename.endswith('.yml') def get_sys_stats(): global sys_cache cpu_usage = 0.0 mem_usage = 0.0 rx_speed = 0.0 tx_speed = 0.0 # 1. 采用与 1Panel 同步的底层 CPU 差值算法 try: with open('/proc/stat', 'r') as f: fields = [float(column) for column in f.readline().strip().split()[1:5]] current_idle = fields[3] current_total = sum(fields) if sys_cache["last_cpu_time"] is not None: last_idle, last_total = sys_cache["last_cpu_time"] idle_delta = current_idle - last_idle total_delta = current_total - last_total if total_delta > 0: cpu_usage = round((1.0 - idle_delta / total_delta) * 100, 1) if cpu_usage < 0.0: cpu_usage = 0.0 if cpu_usage > 100.0: cpu_usage = 100.0 sys_cache["last_cpu_time"] = (current_idle, current_total) except: pass # 2. 精准内存计算 (free -m) try: res = subprocess.run("free -m", shell=True, capture_output=True, text=True) for line in res.stdout.splitlines(): if line.startswith("Mem:"): parts = line.split() total = float(parts[1]) used = float(parts[2]) if total > 0: mem_usage = round((used / total) * 100, 1) break except: pass # 3. 网络流量带宽计算 try: total_rx = 0 total_tx = 0 with open('/proc/net/dev', 'r') as f: lines = f.readlines() for line in lines[2:]: parts = line.split() if len(parts) >= 9 and parts[0] != 'lo:': total_rx += int(parts[1]) total_tx += int(parts[9]) now = time.time() time_diff = now - sys_cache["last_net_time"] if sys_cache["last_rx"] > 0 and time_diff > 0: rx_speed = (total_rx - sys_cache["last_rx"]) / time_diff / 1024 / 1024 tx_speed = (total_tx - sys_cache["last_tx"]) / time_diff / 1024 / 1024 sys_cache["last_net_time"] = now sys_cache["last_rx"] = total_rx sys_cache["last_tx"] = total_tx except: pass return {"cpu": cpu_usage, "mem": mem_usage, "rx": round(rx_speed, 2), "tx": round(tx_speed, 2)} @app.route('/sys-stats') def sys_stats_api(): return jsonify(get_sys_stats()) def run_compile_core(yaml_name, mode='normal', log_mode='w'): global compile_status yaml_full_path = os.path.join(CONFIG_DIR, yaml_name) device_name = get_esphome_device_name(yaml_full_path) or yaml_name.replace('.yaml', '').replace('.yml', '') current_compile_version = get_esphome_docker_version() meta_path = os.path.join(CONFIG_DIR, f"{device_name}_firmware.meta") cmd = f"nice -n 19 docker exec esphome esphome compile /config/{yaml_name}" if mode == 'clean': cmd = f"nice -n 19 docker exec esphome esphome clean /config/{yaml_name} && {cmd}" with open(LOG_FILE, log_mode, encoding="utf-8") as log_f: log_f.write(f"\n\n=================== [{datetime.now().strftime('%H:%M:%S')}] Processing: {yaml_name} ===================\n") log_f.flush() process = subprocess.Popen(cmd, shell=True, stdout=log_f, stderr=subprocess.STDOUT, text=True) process.wait() if process.returncode == 0: build_dir = os.path.join(CONFIG_DIR, ".esphome", "build", device_name, ".pioenvs", device_name) has_firmware = False ota_src = os.path.join(build_dir, "firmware.bin") if os.path.exists(ota_src): os.system(f"cp '{ota_src}' '{os.path.join(CONFIG_DIR, f'{device_name}_firmware.bin')}'") has_firmware = True fac_src = os.path.join(build_dir, "firmware.factory.bin") if os.path.exists(fac_src): os.system(f"cp '{fac_src}' '{os.path.join(CONFIG_DIR, f'{device_name}_factory.bin')}'") has_firmware = True if has_firmware: with open(meta_path, 'w', encoding='utf-8') as meta_f: meta_f.write(current_compile_version) return True, "success" with open(meta_path, 'w', encoding='utf-8') as meta_f: meta_f.write("failed") return False, "" def compile_all_worker(): global compile_status try: yaml_files = [f for f in os.listdir(CONFIG_DIR) if is_valid_esphome_yaml(f)] if not yaml_files: compile_status = {"status": "idle", "message": "No YAML files found."} return total = len(yaml_files) with open(LOG_FILE, 'w', encoding='utf-8') as log_f: log_f.write(f"=== Batch Update Started at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ===\n") for idx, yaml_file in enumerate(yaml_files, 1): compile_status = {"status": "compiling", "message": f"🤖 Batch updating ({idx}/{total}): {yaml_file}"} run_compile_core(yaml_file, mode='normal', log_mode='a') compile_status = {"status": "idle", "message": "🎉 All batchupdate operations completed successfully."} except Exception as e: compile_status = {"status": "idle", "message": f"❌ Error: {str(e)}"} finally: with open(LOG_FILE, 'a', encoding='utf-8') as log_f: log_f.write("\n[DONE]\n") @app.route('/') def index(): files = [] if os.path.exists(CONFIG_DIR): files = [f for f in os.listdir(CONFIG_DIR) if is_valid_esphome_yaml(f)] return render_template('esphome_index.html', files=sorted(files)) @app.route('/start', methods=['POST']) def start_compile(): global compile_status if compile_status["status"] == "compiling": return jsonify({"result": "busy"}) data = request.json yaml_name = data.get('yaml') mode = data.get('mode', 'normal') compile_status = {"status": "compiling", "message": f"⚡ Active updating: {yaml_name}..."} import threading def worker(): global compile_status success, _ = run_compile_core(yaml_name, mode, 'w') if success: compile_status = {"status": "idle", "message": "🟢 Firmware compiled successfully!"} else: compile_status = {"status": "idle", "message": "🔴 Compilation failed."} with open(LOG_FILE, 'a', encoding='utf-8') as log_f: log_f.write("\n[DONE]\n") threading.Thread(target=worker).start() return jsonify({"result": "started"}) @app.route('/start-all', methods=['POST']) def start_compile_all(): global compile_status if compile_status["status"] == "compiling": return jsonify({"result": "busy"}) compile_status = {"status": "compiling", "message": "🚀 Batch update task sequence starting..."} import threading threading.Thread(target=compile_all_worker).start() return jsonify({"result": "started"}) @app.route('/status') def get_status(): return jsonify(compile_status) @app.route('/stream-logs') def stream_logs(): def generate(): if not os.path.exists(LOG_FILE): with open(LOG_FILE, 'w') as f: f.write("") with open(LOG_FILE, 'r', encoding='utf-8', errors='ignore') as f: yield f"data: {f.read()}\n\n" while True: line = f.readline() if line: yield f"data: {line.strip()}\n\n" if "[DONE]" in line: break else: time.sleep(0.1) return Response(generate(), mimetype='text/event-stream') @app.route('/get-last-log') def get_last_log(): log_content = "No log output available." if os.path.exists(LOG_FILE): with open(LOG_FILE, 'r', encoding='utf-8', errors='ignore') as f: log_content = f.read() return jsonify({"log": log_content}) @app.route('/get-firmware-history') def get_firmware_history(): if not os.path.exists(CONFIG_DIR): return jsonify([]) docker_ver = get_esphome_docker_version() links_data = load_links_file() devices_dict = {} for filename in os.listdir(CONFIG_DIR): if filename.endswith('_firmware.bin') or filename.endswith('_factory.bin'): is_factory = filename.endswith('_factory.bin') device_raw_name = filename.replace('_factory.bin', '').replace('_firmware.bin', '') full_path = os.path.join(CONFIG_DIR, filename) mtime = os.path.getmtime(full_path) if device_raw_name not in devices_dict: devices_dict[device_raw_name] = { "device_name": device_raw_name, "time_raw": 0, "ota_url": "", "factory_url": "", "version": "", "device_url": links_data.get(device_raw_name, ""), "is_failed": False } if mtime > devices_dict[device_raw_name]["time_raw"]: devices_dict[device_raw_name]["time_raw"] = mtime devices_dict[device_raw_name]["time"] = datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S') if is_factory: devices_dict[device_raw_name]["factory_url"] = f"/download/{filename}" else: devices_dict[device_raw_name]["ota_url"] = f"/download/{filename}" for dev_name, info in devices_dict.items(): meta_path = os.path.join(CONFIG_DIR, f"{dev_name}_firmware.meta") version = "" if os.path.exists(meta_path): try: with open(meta_path, 'r', encoding='utf-8', errors='ignore') as meta_f: version = meta_f.read().strip() except: pass info["is_failed"] = (version == "failed") if info["is_failed"]: info["version"] = "编译失败" else: if not version or version in ["3", "v3"]: version = docker_ver version = version.replace('vVersion:', '').replace('Version:', '').replace('version:', '').strip() if version.lower().startswith('v'): version = version[1:] info["version"] = f"v{version.strip()}" return jsonify(sorted(list(devices_dict.values()), key=lambda x: x['time_raw'], reverse=True)) @app.route('/download/<filename>') def download_file(filename): from flask import send_from_directory return send_from_directory(CONFIG_DIR, filename, as_attachment=True) @app.route('/save-device-link', methods=['POST']) def save_device_link(): data = request.json dev_name = data.get('device_name') url = data.get('url', '').strip() links = load_links_file() if url: links[dev_name] = url else: if dev_name in links: del links[dev_name] save_links_file(links) return jsonify({"result": "success"}) @app.route('/container-status') def container_status(): try: res = subprocess.run("docker inspect -f '{{.State.Running}}' esphome", shell=True, capture_output=True, text=True) if res.stdout.strip() == 'true': return jsonify({"online": True}) except: pass return jsonify({"online": False}) @app.route('/check-versions') def check_versions(): local_ver = get_esphome_docker_version() return jsonify({"local": local_ver, "latest": local_ver, "update_available": False}) if __name__ == '__main__': app.run(host='0.0.0.0', port=5500)[/collapse]2.2 编辑esphome_index.html[collapse title="代码超长点击展开代码" status="false"] ESPHome Online Build Platform 🛠️ Rose ESPHome Platform CPU:0% RAM:0% ▼0K/s ▲0K/s 检测中... 📦 Compiled History & Devices 刷新 正在扫描固件资产... Select Configuration File: {% for file in files %} {{ file }} {% endfor %} Start Build Clean Build View Log 🚀 Update & Build All Devices (Sequential Serverless Execution) Status: Waiting... Console output layer... [/collapse]3.安装及测试3.1 安装 Python 3 环境及面板依赖由于面板后端是用 Python 的 Flask 框架编写的，且需要读取系统硬件状态，必须先补全宿主机的 Python 环境。在宿主机终端运行以下命令：# 1. 更新系统包索引并安装 Python3 和 Pip 包管理器 apt update && apt apt install -y python3-pip # 2. 安装面板核心依赖（Flask 网页框架 与 psutil 硬件监控库） pip3 install flask psutil3.2 首次手动前台启动（测试与调优）在正式让它长期在后台跑之前，先在终端前台启动一次，方便观察有没有路径报错或权限问题。# 1. 切换到代码所在目录 cd /root # 2. 用 Python 3 启动后端脚本 python3 esphome_panel.py💡 如何判断启动成功？如果终端没有抛出红色报错，并且最后输出类似 Running on all addresses (0.0.0.0) 和 Running on http://127.0.0.1:5500，说明后端已经成功在 5500 端口上监听。3.3 本地跑通验证测试保持刚才启动的终端别关，在同一局域网的电脑上打开浏览器，访问：http://你的服务器局域网IP:5500检查点 A（设备列表）：看左侧是否成功加载出了你挂载目录下的那些 .yaml 设备配置文件。检查点 B（监控状态）：看顶部状态栏的 CPU、内存、Docker 状态（应该显示绿色的 Running）是否开始动态跳动。检查点 C（功能测试）：任选一个设备，点击“标准编译更新”，观察右侧黑色控制台是否开始滚动输出 Docker 编译日志。验证一切正常后，回到终端按 Ctrl + C 结束这个前台进程，接下来把它托管到后台。4.将面板注册为系统服务（开机自启与后台托管）为了不用每次都开着终端窗口，我们需要把面板打包成 Linux 的 Systemd 系统服务，让它在后台默默干活，且跟着服务器一起开机自启。4.1 创建服务配置文件在终端执行以下命令，直接新建服务文件：nano /etc/systemd/system/esphome-panel.service 将以下配置内容完整粘贴进去： Ini, TOML [Unit] Description=ESPHome Online Compile Panel Service # 确保在网络和 Docker 容器都准备好之后再启动面板 After=network.target docker.service Requires=docker.service [Service] Type=simple User=root # 🎯 指定代码和 html 文件所在的实际目录 WorkingDirectory=/root # 🎯 执行启动的完整命令 ExecStart=/usr/bin/python3 /root/esphome_panel.py Restart=always RestartSec=5 [Install] WantedBy=multi-user.target保存并退出（nano 编辑器下按 Ctrl + O 回车保存，再按 Ctrl + X 退出）。4.2 激活并拉起后台服务在终端依次敲入以下三行命令，完成服务的注册与启动：# 1. 刷新系统服务列表，让系统认出刚刚新建的 esphome-panel systemctl daemon-reload # 2. 设置开机自启 systemctl enable esphome-panel.service # 3. 立即启动该服务 systemctl start esphome-panel.service5.日常维护快捷命令服务托管到后台后，以后你只需要用这三行系统命令就能完美控制它：检查面板在后台活得怎么样：systemctl status esphome-panel.service (如果看到绿色的 active (running)，说明在后台很健康)修改了代码或者卡死时，重启面板：systemctl restart esphome-panel.service实时追踪面板后台的最新动作日志：journalctl -u esphome-panel.service -f -n 50
PVE新建的debian11开机6分钟左右，这肯定不正常了，赶紧查看哪里拖慢开机速度systemd-analyze blame经过检查发现是networking.service的锅vi /lib/systemd/system/networking.service那就把networking.service的超时时间修改短点root@nezha:~# cat /lib/systemd/system/networking.service [Unit] Description=Raise network interfaces Documentation=man:interfaces(5) DefaultDependencies=no Requires=ifupdown-pre.service Wants=network.target After=local-fs.target network-pre.target apparmor.service systemd-sysctl.service systemd-modules-load.service ifupdown-pre.service Before=network.target shutdown.target network-online.target Conflicts=shutdown.target [Install] WantedBy=multi-user.target WantedBy=network-online.target [Service] Type=oneshot EnvironmentFile=-/etc/default/networking ExecStart=/sbin/ifup -a --read-environment ExecStop=/sbin/ifdown -a --read-environment --exclude=lo RemainAfterExit=true TimeoutStartSec=5s //修改到5s重启果然快多了
homeassistant环境虚拟机系统：proxmox7.4homeassiatant镜像：https://github.com/home-assistant/operating-/releases/download/11.1/haos_ova-11.1.qcow2.xz创建HA虚拟机（自行搜索创建虚拟机文档）然后通过xftp或者其他工具将解压出来的homeassiatant镜像上传到PVE的/tmp目录ssh登录pve或者直接在pve的控制台用以下命令转换虚拟机镜像qm importdisk 虚拟机ID /tmp/虚拟机镜像.qcow2 保存存储名 转换完后在虚拟机硬件中找到新出现的磁盘，双击然后挂载磁盘挂载完磁盘后记得去虚拟机选项下引导顺序勾选并调整磁盘为第一启动盘在硬件里面添加串行端口这样在虚拟机启动后可以双击虚拟机ID，在弹出的KVM窗口中可以复制粘贴命令开启虚拟机，然后双击左侧虚拟机ID栏，打开KVM窗口，等待虚拟机启动完成,完成时控制台显示ha>_[scode type='red']如果安装失败，请使用特殊科学方式连接网络[/scode]kvm窗口显示如下内容时输入root然后回车Welcome to Home Assistant homeassistant login: #然后显示 homeassistant login: root Last login: Thu Nov 2 16:37:57 UTC 2023 on ttyS0 Last login: Thu Nov 2 17:30:23 on ttyS0 Welcome to Home Assistant OS. Use `ha` to access the Home Assistant CLI. #即表示成功进入root模式然后按如下操做cd /mnt/data/ #进入data目录，因为有些目录没有写权限，会导致后面操作失败 mkdir ddns-go #在data目录下创建ddns-go目录用来给后面创建ddns-go时映射目录DDNS-GO项目地址：https://hub.docker.com/r/jeessy/ddns-go#原映射目录在HA中没有权限，会导致创建失败 docker run -d --name ddns-go --restart=always --net=host -v /opt/ddns-go:/root jeessy/ddns-go #改成刚创建的目录来映射可以成功 docker run -d --name ddns-go --restart=always --net=host -v /mnt/data/:/root jeessy/ddns-go运行成功后用http://HA的IP:9876去访问DDNS-GO配置页面，按照自身需求自行配置相关参数
Debian 11 Bullseye 解决 /etc/rc.local 开机启动问题由于某些软件并没有增加开启启动的服务，很多时候需要手工添加，一般我们都是推荐使用 systemd 写个系统服务，但是对于一些简单的脚本或者懒人来说，添加命令到 /etc/rc.local 文件更方便，但是自从 Debian 9 开始，Debian 默认不带 /etc/rc.local 文件，而 rc.local 服务却还是自带的：root@debian ~ # cat /lib/systemd/system/rc-local.service # SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # This unit gets pulled automatically into multi-user.target by # systemd-rc-local-generator if /etc/rc.local is executable. [Unit] Description=/etc/rc.local Compatibility Documentation=man:systemd-rc-local-generator(8) ConditionFileIsExecutable=/etc/rc.local After=network.target [Service] Type=forking ExecStart=/etc/rc.local start TimeoutSec=0 RemainAfterExit=yes GuessMainPID=no并且默认情况下这个服务还是关闭的状态：root@debian ~ # systemctl status rc-local ● rc-local.service - /etc/rc.local Compatibility Loaded: loaded (/lib/systemd/system/rc-local.service; static) Drop-In: /usr/lib/systemd/system/rc-local.service.d └─debian.conf Active: inactive (dead) Docs: man:systemd-rc-local-generator(8)为了解决这个问题，我们需要手工添加一个 /etc/rc.local 文件：cat <<EOF >/etc/rc.local #!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. exit 0 EOF然后赋予权限：chmod +x /etc/rc.local接着启动 rc-local 服务：systemctl enable --now rc-local此时可能会弹出警告：The unit files have no installation config (WantedBy=, RequiredBy=, Also=, Alias= settings in the [Install] section, and DefaultInstance= for template units). This means they are not meant to be enabled using systemctl. Possible reasons for having this kind of units are: • A unit may be statically enabled by being symlinked from another unit's .wants/ or .requires/ directory. • A unit's purpose may be to act as a helper for some other unit which has a requirement dependency on it. • A unit may be started when needed via activation (socket, path, timer, D-Bus, udev, scripted systemctl call, ...). • In case of template units, the unit is meant to be enabled with some instance name specified.无视警告，因为这个服务没有任何依赖的系统服务，只是开机启动 /etc/rc.local 脚本而已。再次查看状态：root@debian ~ # systemctl status rc-local.service ● rc-local.service - /etc/rc.local Compatibility Loaded: loaded (/lib/systemd/system/rc-local.service; enabled-runtime; vendor preset: enabled) Drop-In: /usr/lib/systemd/system/rc-local.service.d └─debian.conf Active: active (exited) since Thu 2022-01-27 18:52:43 UTC; 10s ago Docs: man:systemd-rc-local-generator(8) Process: 541 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS) CPU: 3ms Jan 27 18:52:43 debian systemd[1]: Starting /etc/rc.local Compatibility... Jan 27 18:52:43 debian systemd[1]: Started /etc/rc.local Compatibility.然后你就可以把需要开机启动的命令添加到 /etc/rc.local 文件，丢在 exit 0 前面即可，并尝试重启以后试试是否生效了。常用命令sudo systemctl enable rc-local # 启用 sudo systemctl start rc-local.service # 开始运行 sudo systemctl status rc-local.service # 查看状态清空操作历史# 第一步： 删除 .bash_history 文件 rm -rf ~/.bash_history # 第二步： 清空命令历史记录 history -c
国内常见镜像站点阿里云镜像站deb https://mirrors.aliyun.com/debian/ bullseye main non-free contrib deb-src https://mirrors.aliyun.com/debian/ bullseye main non-free contrib deb https://mirrors.aliyun.com/debian-security/ bullseye-security main deb-src https://mirrors.aliyun.com/debian-security/ bullseye-security main deb https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib deb-src https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib deb https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib deb-src https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib腾讯云镜像站deb https://mirrors.tencent.com/debian/ bullseye main non-free contrib deb-src https://mirrors.tencent.com/debian/ bullseye main non-free contrib deb https://mirrors.tencent.com/debian-security/ bullseye-security main deb-src https://mirrors.tencent.com/debian-security/ bullseye-security main deb https://mirrors.tencent.com/debian/ bullseye-updates main non-free contrib deb-src https://mirrors.tencent.com/debian/ bullseye-updates main non-free contrib deb https://mirrors.tencent.com/debian/ bullseye-backports main non-free contrib deb-src https://mirrors.tencent.com/debian/ bullseye-backports main non-free contrib网易镜像站deb https://mirrors.163.com/debian/ bullseye main non-free contrib deb-src https://mirrors.163.com/debian/ bullseye main non-free contrib deb https://mirrors.163.com/debian-security/ bullseye-security main deb-src https://mirrors.163.com/debian-security/ bullseye-security main deb https://mirrors.163.com/debian/ bullseye-updates main non-free contrib deb-src https://mirrors.163.com/debian/ bullseye-updates main non-free contrib deb https://mirrors.163.com/debian/ bullseye-backports main non-free contrib deb-src https://mirrors.163.com/debian/ bullseye-backports main non-free contrib华为镜像站deb https://mirrors.huaweicloud.com/debian/ bullseye main non-free contrib deb-src https://mirrors.huaweicloud.com/debian/ bullseye main non-free contrib deb https://mirrors.huaweicloud.com/debian-security/ bullseye-security main deb-src https://mirrors.huaweicloud.com/debian-security/ bullseye-security main deb https://mirrors.huaweicloud.com/debian/ bullseye-updates main non-free contrib deb-src https://mirrors.huaweicloud.com/debian/ bullseye-updates main non-free contrib deb https://mirrors.huaweicloud.com/debian/ bullseye-backports main non-free contrib deb-src https://mirrors.huaweicloud.com/debian/ bullseye-backports main non-free contrib清华大学镜像站deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free中科大镜像站deb https://mirrors.ustc.edu.cn/debian/ bullseye main contrib non-free deb-src https://mirrors.ustc.edu.cn/debian/ bullseye main contrib non-free deb https://mirrors.ustc.edu.cn/debian/ bullseye-updates main contrib non-free deb-src https://mirrors.ustc.edu.cn/debian/ bullseye-updates main contrib non-free deb https://mirrors.ustc.edu.cn/debian/ bullseye-backports main contrib non-free deb-src https://mirrors.ustc.edu.cn/debian/ bullseye-backports main contrib non-free deb https://mirrors.ustc.edu.cn/debian-security/ bullseye-security main contrib non-free deb-src https://mirrors.ustc.edu.cn/debian-security/ bullseye-security main contrib non-free使用方法vi /etc/apt/sources.list #编辑源文件 sudo apt-get update #编辑完成后保存退出后更新源列表
编辑配置文件nano /etc/ssh/sshd_config #编辑配置 PasswordAuthentication yes #允许使用密码登录 PermitRootLogin yes #允许root认证登录，然后Ctrl+x按提示输入Y保存退出 service ssh restart #重启ssh服务安装ifconfigapt-get install net-tools
1 <?php 2 /** 3 这个是php版的代码 4 要先准备一台一个站群服务器，建议一整个c段253IP以上的服务器 5 原理是，假墙封ip几个小时，每1分钟换一次解析，轮流使用250多个ip使其超过他封禁时间 6 用linux定时任务，每一分钟运行此一次：如新建网站，保存此文件名为q.php,网站端口4521，宝塔提交定时url任务 ： http://127.0.0.1:4521/q.php 7 **/ 8 9 $file = './tqdata.txt'; // 同目录下新建tqdata.txt文件，里面填个数字 比如 1，用来记录当前使用的 10 $txt = file_get_contents($file); 11 $ips = []; 12 for($i=1; $i <=254; $i++){ 13 $ips[$i] = '45.45.45.' . $i; // 自己的ip 14 } 15 16 $ip = $ips[$txt]; 17 // 进cf解析页f12,找到那条记录，提交，得到下面的提交地址 xxxx是需要替换成自己的 18 $www='https://api.cloudflare.com/client/v4/zones/xxxx/dns_records/xxxx'; 19 20 $datawww = array( 21 "type"=>"A", 22 "name"=>"www.domain.com", 23 "content"=>$ip, 24 "ttl"=>120, 25 "proxied"=>false 26 ); 27 28 29 curl_get($www,$datawww); 30 31 function curl_get($url,$data) 32 { 33 $ch = curl_init(); 34 $headers = array( 35 'X-Auth-Email:自己cf的账号', 36 'X-Auth-Key:自己cf的key', 37 'Content-Type:application/json' 38 ); 39 $data = json_encode($data); 40 $ch = curl_init(); //初始化CURL句柄 41 curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 42 curl_setopt($ch, CURLOPT_URL, $url); //设置请求的URL 43 curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); //设为TRUE把curl_exec()结果转化为字串，而不是直接输出 44 curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"PUT"); //设置请求方式 45 curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//设置提交的字符串 46 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书 47 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名 48 $output = curl_exec($ch); 49 curl_close($ch); 50 return json_decode($output,true); 51 }
1. apt-get update报错apt-get update --allow-releaseinfo-change2. LXC容器开启SSH访问nano /etc/ssh/sshd_config 添加 `PermitRootLogin yes` Ctrl+x 保持退出
环境机器：暴风二期的机器，当时抄底800大洋拿下的 系统：EXSI 7.0 好像是，当时开的直通4T硬盘，U盘引导当然也是直通上去的，就是怕ESXI哪天挂B了，可以直接拔盘使用，结果ESXI真TM稳的一批事发经过我的黑裙忘了是我作死断电还是当时片区几次断电~后~，我的黑裙就连不上了，当时觉得没事，事实证明粗大事了，真的是访问不了了，OMG，当时心里依然不慌，大不了重新做系统分区，当兴致冲冲的把系统分区在PE下格掉后，重新挂上U盘引导，插电，开机，不出意外的出了意外，安装系统那步当提示我格式化整个硬盘，当时心里一万匹羊驼驰骋，本着破罐子破摔的态度，我选择了关机，TMD 4T的大姐姐你说格就格，你当我疯了，我跟你没完 就这样兜兜转转没想好怎么处理，又不舍得再买一块大硬盘，一拖就是半年，最近又入手了两台满配锐角云，那还不继续折腾起来，插电，开机，无量奸商，竟然卖了我一块坏的电源，害我以为翻车了，还好12V电源一大堆，装好PVE系统，赶紧装个deepin把硬盘挂上去，资料都可以访问，但是吧怎么转出来备份一下，毕竟自己今日不同往昔了，兄嘚也有E5订阅了，但是怎么备份呢，折腾了半天发现真麻烦，一点都不符合我这种小白的气质，那怎么办呢，要不直接挂群晖里用群晖的cloud sync 岂不是美滋滋，说干就干开干了PVE安装黑裙，这个我就不讲了，自己搞去群晖安装完后开启 ssh, [scode type='yellow']然后创建个共享文件夹并查看文件夹属性，记下此文件夹的路径等下要用[/scode]，当然你cloud sync 也装下啊，硬盘拿移动硬盘盒自己插USB口子上，你在群晖控制面板的外接设备可以看到你的磁盘了吧，但是你就是访问不了，你说气不气，哈哈哈哈哈ssh 登录群晖后当然是 sudo -i 切换到root用户了，然后输入fdisk -l[scode type='yellow']在列表中找到你的磁盘对应的路径，我的是Disk /dev/md9: 3.6 TiB, 3995849261056 bytes, 7804393088 sectors所以我记住/dev/md9就是等下要挂载的路径了[/scode]然后输入上面两处路径分别对应磁盘路径和映射路径，这时候你再登录群晖，在file station里就可以愉快的访问里面的文件了，接下来要做的当然是TM的转移备份啊，挂起E5开始疯狂吧，我已经备份了3天了还没完，里面的小文件太多也懒得管了，等备份完就拿之前装ESXI的2T固态去把大文件对拷出来，剩下的小文件到时候等插上4T盘再去慢慢自己同步去
win10访问玩客云报错“Windows 找不到“\\192.168.1.111”。请检查拼写并重试。”
Windows 找不到“\192.168.1.111”。请检查拼写并重试。系统环境Win10 LTSC一度以为是自己问题，没想到是系统问题，网上还一堆驴唇不对马嘴的垃圾方法，又是什么服务的，又是注册表的，我去你奶奶个腿儿的解决方案：1、按Win键弹出开始菜单，直接在键盘上复制粘贴“编辑组策略”，搜到这个程序直接打开。2、本地组策略编辑器，顺着左侧的策略树，找到“计算机配置-管理模板-网络-Lanman工作站”这个节点，在右侧内容区可以看到“启用不安全的来宾登录”这一条策略设置。状态是“未配置”。双击“启用不安全的来宾登录”这一条策略设置，将其状态修改为“已启用”并单击确定按钮。3、重新访问即可食用。