import subprocess
import glob
import time
import os
import shutil
from pathlib import Path
BACKUP_DIR = r"C:\Users\Administrator\Documents\XuanZhi64\Pictures"
LD_DIR = r"D:\LDPlayer\LDPlayer64" VMS_CONFIG_DIR = LD_DIR + r"\vms\config"
BACKUP_CMD = "cd /data && tar -zhpcf /sdcard/Pictures/{}_data.tar.gz . --exclude=local --exclude=app " \"--exclude=user_de/0/com.google.android.tts --exclude=dalvik-cache --exclude=tombstones " \"--exclude=system_de/0/ringtones --exclude=misc --exclude=app-lib --exclude=media --exclude=ota " \"--exclude=property --exclude=adb --exclude=anr --exclude=app-asec;exit\n "
ROLLBACK_CMD = "cd /data && tar -zxf /sdcard/Pictures/{}_data.tar.gz;exit\n"
os. chdir( LD_DIR)
ba = glob. glob( f" { VMS_CONFIG_DIR} \\leidian[0-9]*.config" )
ld_count = len ( ba) def backup ( dst_ld_index, is_rollback= False , rollback_from_other_index= None ) : rollback_index = dst_ld_indexif is_rollback and isinstance ( rollback_from_other_index, int ) : rollback_index = rollback_from_other_indexbackup_config_path = f" { BACKUP_DIR} / { rollback_index} .config" backup_datagz_path = f" { BACKUP_DIR} / { rollback_index} _data.tar.gz" if is_rollback: if not Path( backup_config_path) . exists( ) or not Path( backup_datagz_path) . exists( ) : print ( "恢复到模拟器失败,先备份再进行还原" ) return - 2 p = subprocess. Popen( f"ld -s { dst_ld_index} " , shell= True , universal_newlines= True , stdin= subprocess. PIPE, stdout= subprocess. PIPE) time. sleep( 1 ) if isinstance ( p. poll( ) , int ) and p. poll( ) > 0 : return p. poll( ) if p. poll( ) is None : if not is_rollback: p. stdin. write( BACKUP_CMD. format ( dst_ld_index) ) else : p. stdin. write( ROLLBACK_CMD. format ( rollback_index) ) p. stdin. flush( ) wait_count = 0 start = time. time( ) while p. poll( ) is None : wait_count += 1 time. sleep( 1 ) if wait_count > 3 : print ( "备份超时 > {}s" . format ( wait_count) ) break end = time. time( ) print ( "备份完成,耗时{}秒" . format ( int ( end - start) ) ) if not is_rollback: shutil. copyfile( f" { VMS_CONFIG_DIR} /leidian { dst_ld_index} .config" , backup_config_path) else : for i in range ( 5 ) : time. sleep( 10 ) test( dst_ld_index, rollback_index) return p. poll( ) return - 1 def test ( dst_ld_index, rollback_index) : subprocess. check_call( f"ldconsole.exe quit --index { dst_ld_index} " , shell= True , stderr= subprocess. PIPE) time. sleep( 10 ) backup_config_path = f" { BACKUP_DIR} / { rollback_index} .config" shutil. copyfile( backup_config_path, f" { VMS_CONFIG_DIR} /leidian { dst_ld_index} .config" ) subprocess. check_call( f"ldconsole.exe launch --index { dst_ld_index} " , shell= True , stderr= subprocess. PIPE) print ( dst_ld_index, rollback_index) def shell_mode ( ) : tips = f"""雷电模拟器数据备份工具 1.0 ### (当前扫描到 { ld_count} 个模拟器) { ", " . join( [ str ( i) for i in range ( ld_count) ] ) } 使用方法:1. 输入b11 备份11号模拟器2. 输入h11 从11号模拟器数据还原到11号模拟器数据3. 输入h11-2 从 2号模拟器数据还原到11号模拟器数据4. 输入ba 备份所有模拟器5. 输出ha 还原所有模拟器""" print ( tips) while True : cmd = input ( "\n>> 输入下一步操作指令\n" ) ret = - 16 if cmd == "ba" : print ( "开始备份所有模拟器" ) for i in range ( ld_count) : ret = backup( i) print ( f"备份模拟器 { i} ,返回码: { ret} (0是正常)" ) continue elif cmd == "ha" : print ( "开始还原所有模拟器" ) for i in range ( ld_count) : ret = backup( i, is_rollback= True ) print ( f"还原模拟器 { i} ,返回码: { ret} (0是正常)" ) continue elif "h" in cmd and "-" in cmd: ld_index = int ( cmd. split( "-" ) [ 0 ] [ 1 : ] ) rollback_from_index = int ( cmd. split( "-" ) [ 1 ] ) print ( f"还原模拟器 { ld_index} , 数据来源: { rollback_from_index} " ) ret = backup( ld_index, True , rollback_from_index) elif "h" in cmd: ld_index = int ( cmd[ 1 : ] ) print ( f"还原模拟器 { ld_index} " ) ret = backup( ld_index, True ) elif "b" in cmd: ld_index = int ( cmd[ 1 : ] ) print ( f"备份模拟器 { ld_index} " ) ret = backup( ld_index) else : print ( "执行代码指令:" + cmd) eval ( cmd) continue print ( f"执行完成, 返回码: { ret} (0是正常)" ) if __name__ == "__main__" : shell_mode( )