服务器损坏,数据迁移,只有一个链接窗口的情况下

🔹 阶段 1:生成"权威文件清单"(manifest)

这是"文件完整性的法律文件",后面一切都以它为准

✅ 在【源服务器】执行(非常快、只读)

复制代码
cd /opt/jyd01/wangruihua/api_docker/jyd_digital

python3 - << 'EOF'
import os, json

BASE = "jyd_heygem"
files = []

for root, dirs, filenames in os.walk(BASE):
    for name in filenames:
        full = os.path.join(root, name)
        try:
            size = os.path.getsize(full)
        except:
            continue
        rel = os.path.relpath(full, BASE)
        files.append({"path": rel, "size": size})

print("TOTAL files:", len(files))

with open("jyd_heygem_manifest.json", "w") as f:
    json.dump(files, f)
EOF

你会看到类似:

复制代码
TOTAL files: 61388

注意:manifest 放在 jyd_digital 目录,不在项目目录里

项目目录下会生成jyd_heygem_manifest.json

✅ 在【新服务器】新建目录:jyd_heygem

目录下新建文件:receiver_9501.py

复制代码
import socket, os, struct

HOST = ''
PORT = 9501
BASE = os.getcwd()
CHUNK = 1024 * 1024  # 1MB

def recv_exact(conn, n):
    buf = b''
    while len(buf) < n:
        chunk = conn.recv(n - len(buf))
        if not chunk:
            return None
        buf += chunk
    return buf

s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
print("READY on", PORT)

conn, addr = s.accept()
print("Connected", addr)

count = 0

while True:
    hdr = recv_exact(conn, 4)
    if hdr is None:
        break

    path_len = struct.unpack("!I", hdr)[0]
    path_bytes = recv_exact(conn, path_len)
    if path_bytes is None:
        break
    path = path_bytes.decode("utf-8", errors="replace")

    size_bytes = recv_exact(conn, 8)
    if size_bytes is None:
        break
    size = struct.unpack("!Q", size_bytes)[0]

    full_path = os.path.join(BASE, path)
    os.makedirs(os.path.dirname(full_path), exist_ok=True)

    remaining = size
    with open(full_path, "wb") as f:
        while remaining > 0:
            chunk = conn.recv(min(CHUNK, remaining))
            if not chunk:
                break
            f.write(chunk)
            remaining -= len(chunk)

    # 关键:ACK
    conn.sendall(b"OK")

    count += 1
    if count % 50 == 0:
        print("Received files:", count)

print("DONE total:", count)
conn.close()
s.close()

在jyd_heygem目录下运行

复制代码
python3 receiver_9501.py

必须看到这两行:

复制代码
READY on 9501 
Connected ('188.18.18.149', xxxxx)

接收完成

✅ 在【源服务器】新建文件:sender_9501.py

复制代码
import socket
import os
import struct
import json
import time

# ================== 配置区 ==================
HOST = "188.18.18.149"   # 目标服务器 IP
PORT = 9501              # 必须和 receiver 一致
BASE = "jyd_heygem"    # 要发送的目录
MANIFEST = "jyd_heygem_manifest.json"
CHUNK = 1024 * 1024      # 1MB
# ============================================


def send_file(sock, base, rel_path, size):
    """
    发送单个文件(分块)
    """
    full_path = os.path.join(base, rel_path)

    # 发送头
    sock.sendall(struct.pack("!I", len(rel_path)))
    sock.sendall(rel_path.encode("utf-8"))
    sock.sendall(struct.pack("!Q", size))

    remaining = size
    with open(full_path, "rb") as f:
        while remaining > 0:
            data = f.read(min(CHUNK, remaining))
            if not data:
                raise IOError("Unexpected EOF while reading file")
            sock.sendall(data)
            remaining -= len(data)


def main():
    # 读取 manifest
    with open(MANIFEST, "r") as f:
        files = json.load(f)

    total = len(files)
    print(f"[INFO] Manifest loaded: {total} files")

    # 建立连接
    sock = socket.socket()
    sock.connect((HOST, PORT))
    print(f"[INFO] Connected to {HOST}:{PORT}")

    sent = 0
    skipped = 0

    start_time = time.time()

    for item in files:
        rel_path = item["path"]
        size = item["size"]
        full_path = os.path.join(BASE, rel_path)

        # 文件可读性检查
        if not os.path.exists(full_path):
            print(f"[SKIP] Missing file: {rel_path}")
            skipped += 1
            continue

        try:
            send_file(sock, BASE, rel_path, size)
        except Exception as e:
            print(f"[ERROR] Sending {rel_path}: {e}")
            skipped += 1
            continue

        # 等待 ACK
        try:
            ack = sock.recv(2)
        except Exception as e:
            print(f"[ERROR] ACK failed on {rel_path}: {e}")
            break

        if ack != b"OK":
            print(f"[ERROR] Invalid ACK on {rel_path}: {ack}")
            break

        sent += 1
        if sent % 50 == 0:
            elapsed = int(time.time() - start_time)
            print(f"[PROGRESS] Sent {sent}/{total} files | {elapsed}s elapsed")

    sock.close()

    print("===================================")
    print(f"[DONE] Sent: {sent}")
    print(f"[DONE] Skipped: {skipped}")
    print(f"[DONE] Manifest total: {total}")
    print("===================================")


if __name__ == "__main__":
    main()

运行:pytohn sender_9501.py

发送完成

三、启动顺序(非常重要)

✅ 1️⃣ 先在目标服务器启动接收端

复制代码
python3 receiver_9501.py

必须看到:

复制代码
READY on 9501

✅ 2️⃣ 再在源服务器启动发送端

复制代码
python3 sender_9501.py

你应该看到类似:

复制代码
[INFO] Manifest loaded: 12345 files 
[INFO] Connected to 188.18.18.149:9501 
[PROGRESS] Sent 50/12345 files | 12s elapsed 
[PROGRESS] Sent 100/12345 files | 25s elapsed ... 
[DONE] Sent: 12345 [DONE] Skipped: 0 [DONE] Manifest total: 12345

四、最终一致性校验(测试"项目能不能跑")

相关推荐
TTBIGDATA1 小时前
【knox】User: knox is not allowed to impersonate admin
大数据·运维·ambari·hdp·trino·knox·bigtop
佑白雪乐1 小时前
<Linux基础第10集>复习前面内容
linux·运维·服务器
春日见1 小时前
自动驾驶规划控制决策知识点扫盲
linux·运维·服务器·人工智能·机器学习·自动驾驶
玉树临风江流儿2 小时前
docker镜像加速器配置步骤
运维·docker·容器
China_Yanhy3 小时前
我的区块链运维日记 · 第 11 日:生死时速 —— 闪电贷攻击与“红色按钮”
运维·区块链
2401_840192273 小时前
怎么把运维能力沉淀下来?
运维
landonVM3 小时前
Linux 上搭建 Web 服务器
linux·服务器·前端
云游云记3 小时前
nesbot/carbon 常用功能总结
linux·运维·服务器
landonVM3 小时前
Linux 下的高效压缩工具 Zstandard
linux·运维·服务器