python3实现类似expect shell的交互式与SFTP的脚本
前面写过一篇关于python实现类似expect shell的交互式能力的文章,现在补全一下加上sftp的能力脚本。
例子在代码中__example()方法。
依赖paramiko库,所以需要执行pip install paramiko来安装。
import os
import queue
import re
import threading
import time
import traceback
import stat
import datetimeimport paramiko
from paramiko import SSHClient, SSHException, SFTPClient, Channelclass SFTPMultipleClient(object):"""支持多sftp连接拉取文件支持快捷执行远程命令"""def __init__(self, host, port, username, pwd, work_count=1) -> None:super().__init__()# client = SSHClient()# client.set_missing_host_key_policy(paramiko.AutoAddPolicy())# client.connect(hostname=host, timeout=60, port=port, username=username, password=pwd)# self.ssh_client = client# self.sftp_client = client.open_sftp()self.host = hostself.port = portself.username = usernameself.pwd = pwdself.work_count = work_countself.thread_local_data = threading.local()self.pull_queue = queue.Queue()self.ssh_clientlist = []self.sftp_clientlist = []self.thread_list = {}self.email_send_files = []self.ptySessions = [](self.ssh_client, self.sftp_client) = self._gen_sftp_client(host, port, username,pwd) # type:(SSHClient, SFTPClient)for i in range(work_count):self.thread_list[self._start_back_task(self._pull_event_handler)] = Falsedef _start_back_task(self, fun, args=()):t = threading.Thread(target=fun, daemon=True, args=args)t.start()return tdef remote_scp_progress(self, a, b):"""远程scp进度打印:param a: 当前已传输大小(单位字节):param b: 文件总大小(单位字节)"""if a > b:a = bsecond = self.thread_local_data.timer.last_press_time_deltaif second > 1 or a == b:self.thread_local_data.timer.press()speed = a - self.thread_local_data.last_progressself.thread_local_data.last_progress = aremaining_time_second = (b - a) / speeds = self.thread_local_data.get_file_desc + "%s %s %02d%s %dKB/s %02d:%02d " % \(a, b, int(a / b * 100), "%", speed / 1024, remaining_time_second / 60, remaining_time_second % 60)print(s)# print(s, end="", flush=True)# _back = ""# for i in range(len(s)):# _back += '\b'# print(_back, end="")def _gen_sftp_client(self, host, port, username, pwd) -> (SSHClient, SFTPClient):"""生成sftp客户端当连接断开会进行重试,最大重试连接5次"""_try_count = 0_ssh_client = SSHClient()_ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())_sftp_client = Nonetname = threading.current_thread().namestime = 1while _try_count < 5:connect_failed = Falsetry:_ssh_client.connect(hostname=host, timeout=60, port=port, username=username,password=pwd)_sftp_client = _ssh_client.open_sftp()print(tname + " ssh连接成功.")breakexcept Exception as e:connect_failed = Truetraceback.print_exc()if connect_failed:try:_ssh_client.close()if _sftp_client:_sftp_client.close()except Exception as e:traceback.print_exc()_try_count += 1if _try_count == 5:raise Exception("尝试重新连接达到最大次数.断开连接.")traceback.print_exc()print(tname + " 第%d次重新连接ssh..." % _try_count)stime *= 2time.sleep(stime)self.ssh_clientlist.append(_ssh_client)self.sftp_clientlist.append(_sftp_client)self.thread_local_data.ssh_client = _ssh_clientself.thread_local_data.sftp_client = _sftp_clientreturn _ssh_client, _sftp_clientdef _pull_event_handler(self):"""拉取任务处理"""self._gen_sftp_client(self.host, self.port, self.username, self.pwd)# self.thread_local_data.ssh_client = _ssh_client# self.thread_local_data.sftp_client = _sftp_clientwhile True:self.thread_list[threading.current_thread()] = Falsedata = self.pull_queue.get(block=True, timeout=None)self.thread_list[threading.current_thread()] = True# 通过队列插入None来结束线程,如果有n个线程在监听队列,那么需要n个None来结束if data is None:self.thread_list[threading.current_thread()] = Falsebreaktry:self._remote_scp(self.thread_local_data.ssh_client, self.thread_local_data.sftp_client,data.remote_path,data.local_path, data.max_size, callback=self.remote_scp_progress)fun = data.call_bak_funif fun:call_bak_fun_args = ()call_bak_fun_kwargs = {}if type(fun) in [list, tuple]:if not callable(fun[0]):raise Exception("call_bak_fun 不是可调用对象")if len(fun) > 1:call_bak_fun_args = fun[1]if len(fun) > 2:call_bak_fun_kwargs = fun[2]else:if not callable(fun):raise Exception("call_bak_fun 不是可调用对象")fun[0](*call_bak_fun_args, **call_bak_fun_kwargs)except Exception as e:traceback.print_exc()# pull_queue.put(data)# print("线程%s 结束." % threading.current_thread().name)def _remote_scp(self, _ssh_client, _sftp_client, _remote_path, _local_path, max_size=None, callback=None):reconnect = Falsetry:if os.path.exists(_local_path):rf_stat = _sftp_client.lstat(_remote_path)lf_stat = os.stat(_local_path)if rf_stat.st_size == lf_stat.st_size:print(_local_path + " already exists.")returnif max_size and rf_stat.st_size > max_size: # 如果大于1m则认为是空板图片print(_local_path + " > " + max_size + " skipped.")returnprint(threading.current_thread().name + "copy file:%s << %s\t" % (_local_path, _remote_path))self.thread_local_data.get_file_desc = "copy file:%s << %s\t" % (_local_path, _remote_path)self.thread_local_data.timer = Timer()self.thread_local_data.last_progress = 0_sftp_client.get(_remote_path, _local_path, callback=callback)except FileNotFoundError as e:traceback.print_exc()print("continue...")except SSHException as e:traceback.print_exc()reconnect = Trueexcept OSError as e:print("os error====")traceback.print_exc()reconnect = Trueif reconnect:print("重新连接ssh...")_sftp_client.close()_ssh_client.close()self.sftp_clientlist.remove(_sftp_client)self.ssh_clientlist.remove(_ssh_client)_ssh_client, _sftp_client = self._gen_sftp_client(self.host, self.port, self.username, self.pwd)self._remote_scp(_ssh_client, _sftp_client, _remote_path, _local_path, max_size, callback)if callback:print()def pull_file(self, remote_path, local_path, max_size=None, print_progress=False):"""拉取文件:param remote_path: 远程文件路径:param local_path: 本地文件路径:param max_size: 远程文件如果超过了这个大小,则不做拉取:param print_progress: 是否打印文件拉取进度"""if print_progress:self._remote_scp(self.ssh_client, self.sftp_client, remote_path, local_path, max_size,self.remote_scp_progress)else:self._remote_scp(self.ssh_client, self.sftp_client, remote_path, local_path, max_size)def submit_pull_work(self, remote_path, local_path, max_size=None, call_bak_fun=None):"""提交拉取文件任务:param remote_path: 远程文件路径:param local_path: 本地文件路径:param max_size: 远程文件如果超过了这个大小,则不做拉取:param call_bak_fun: 拉取完成回调方法"""e_data = Task(remote_path, local_path, max_size, call_bak_fun)self.pull_queue.put(e_data)def exec_command(self, command, *args, raise_e=True, **kwargs):"""执行远程命令"""stdin, stdout, stderr = self.ssh_client.exec_command(command, *args, **kwargs)if raise_e and stdout.channel.recv_exit_status() != 0:raise Exception(stderr.readline())return stdin, stdout, stderrdef mkdir(self, path, recursive=True, mode=0o777):"""创建文件夹:param path: 远程文件夹:param recursive: 是否递归创建 默认true:param mode: 权限,默认0o777-全部权限"""if not recursive:self.sftp_client.mkdir(path, mode)returndirs = path.split(os.path.sep)current_dir = "/"for i, d in enumerate(dirs):d = os.path.join(current_dir, d)create = Truetry:if stat.S_ISDIR(self.sftp_client.stat(d).st_mode):create = Falseexcept FileNotFoundError:create = Trueif create:self.sftp_client.mkdir(d, mode)current_dir = ddef destroy(self):"""销毁当前实例"""while not self.pull_queue.empty(): # 等待队列任务处理完毕time.sleep(0.2)# 结束线程for thread in self.thread_list:self.pull_queue.put(None) # 通过None来停止线程while True:if thread.is_alive() and self.thread_list[thread]:time.sleep(1)else:break# self.thread_list.pop(thread)# for i in range(len(self.thread_list)):# self.pull_queue.put(None) # 通过None来停止线程# self.thread_list.pop() # 移除成员for ptySession in self.ptySessions:ptySession.destroy()for i in range(len(self.sftp_clientlist)):sftp_client = self.sftp_clientlist.pop()sftp_client.close()for i in range(len(self.ssh_clientlist)):ssh_client = self.ssh_clientlist.pop()ssh_client.close()def __enter__(self):return selfdef __exit__(self, exc_type, exc_val, exc_tb):self.destroy()def open_pty_session(self, ending_char, timeout=30):"""从当前channel开启一个session并激活@return:"""_session = self.ssh_client.get_transport().open_session(timeout=1 * 3600) # type:Channel_session.get_pty()_session.invoke_shell()_ptysession = PtySession(_session, ending_char=ending_char, timeout=timeout)self.ptySessions.append(_ptysession)return _ptysessiondef listdir_attr(self, path):"""列出远程目录:param path: 远程目录:return: list of `.SFTPAttributes` objects"""_reconnect = Falsetry:return self.sftp_client.listdir_attr(path)except SSHException as e:traceback.print_exc()_reconnect = Trueexcept OSError as e:traceback.print_exc()_reconnect = Trueif _reconnect:print("重新连接ssh...")self.sftp_client.close()self.ssh_client.close()self.sftp_clientlist.remove(self.sftp_client)self.ssh_clientlist.remove(self.ssh_client)self.ssh_client, self.sftp_client = self._gen_sftp_client(self.host, self.port, self.username, self.pwd)return self.listdir_attr(path)# 一次读取字节长度
recv_len = 1024 * 5class Task(object):def __init__(self, remote_path, local_path, max_size=None, call_bak_fun=None) -> None:super().__init__()self.remote_path = remote_path # 远程路径self.local_path = local_path # 本地路径self.max_size = max_size # 最大大小,当大于这个大小将跳过不做处理self.call_bak_fun = call_bak_fun # 回调方法 格式:(fn,arg,kw)class PtySession(object):def __init__(self, session, ending_char, timeout=30) -> None:super().__init__()self.session = session # type:Channelself.last_line = ""self.ending_char = ending_char # 每执行一个命令之后,标记输出的结束字符self.clear_tail()self.timeout = timeout # 超时时间,秒def clear_tail(self, _ending_char=None):"""清理输出还处于缓冲区中未读取的流"""if not _ending_char:_ending_char = self.ending_charwhile True:time.sleep(0.2)# self.session.recv_ready()在读取过程中不一定总是True,只有当读取缓冲流中有字节读取时,才会为True。所以在读取头一次后获取下次流到缓冲区中前为Falseif self.session.recv_ready():self.last_line = self.session.recv(recv_len)self.last_line = self.last_line.decode('utf-8')print(self.last_line)if re.search(_ending_char, self.last_line):breakdef destroy(self):"""销毁并关闭session:return::rtype:"""self.clear_tail()self.session.close()def exp(self, *exp_cmds):"""期望并执行,与expect的用法类似。session.exp(("\$", "scp test.txt luckydog@127.0.0.1:~/\r",(("yes/no", "yes\r",("Password:", "luckydog\r")),("Password:", "luckydog\r")))):param exp_cmds: 第一个元素为获取的期望结束字符,第二个元素为需要执行的命令,如果传入的第三个元素,则第三个元素必须为元祖,并且也同父级一样,属递归结构。类似GNU的递归缩写。:type exp_cmds: tuple"""interval = 0.2cur_time = 0.0try:while True:if self.session.recv_ready():self.last_line = self.session.recv(recv_len).decode('utf-8')print(self.last_line)elif self.session.send_ready():for exp_cmd in exp_cmds:_cmd = exp_cmd[1]if not _cmd.endswith("\r"):_cmd += "\r"match = re.search(exp_cmd[0], self.last_line)if match and match.group():self.session.send(_cmd)# 清空最后一行数据缓存,便于下个命令的读取流输出。此行代码去除,会导致无法等待命令执行完毕提前执行后续代码的问题。self.last_line = ""if len(exp_cmd) == 3 and exp_cmd[2]:self.exp(*exp_cmd[2])returncur_time += intervalif cur_time >= self.timeout:raise Exception("timeout...")time.sleep(interval)except Exception as e:traceback.print_exc()# finally:# self.clear_tail()def send(self, cmd, _ending_char=None):"""单纯的发送命令到目标服务器执行。:param cmd: 命令:type cmd: str"""self.last_line = ""if not cmd.endswith("\r"):cmd += "\r"self.session.send(cmd)self.clear_tail(_ending_char)# -----------------------
class Timer(object):def __init__(self) -> None:super().__init__()self._start_time = Noneself._end_time = Noneself._seconds_delta = Noneself._last_press_time = None # 最后一个计次时间def start(self):if not self._start_time:self._start_time = datetime.datetime.now()self._last_press_time = self._start_timeelse:raise Exception("timer is already started.")return self._start_timedef end(self):if not self._end_time:self._end_time = datetime.datetime.now()self._seconds_delta = (self._end_time - self._start_time).total_seconds()else:raise Exception("timer is already stopped.")def press(self):if not self._start_time:self._last_press_time = self.start()return 0now = datetime.datetime.now()last_time = self._last_press_timeself._last_press_time = nowreturn (now - last_time).total_seconds()@propertydef last_press_time_delta(self):if not self._last_press_time:self.press()return 0return (datetime.datetime.now() - self._last_press_time).total_seconds()@propertydef start_time(self):return self._start_time@propertydef end_time(self):return self._end_timedef timedelta_seconds(self):if self._seconds_delta:return self._seconds_deltaelse:raise Exception("timer not stopped.")# ===================test=========================
def _file_pull_complete(filename, **kw):print(filename + "文件上传完成")def __example():sftp = SFTPMultipleClient(host="130.16.16.18", port=22, username="baiyang", pwd="xxx")# 创建目录sftp.mkdir("/home/username/123/")# 下载文件到本地(同步执行)sftp.pull_file("/home/username/temp/rumenz.img", # 远程文件"/Users/username/rumenz.img", # 本地路径文件,需要带上文件名print_progress=True # 打印文件拉取进度)# 提交下载远程文件异步任务(异步线程执行不阻塞)sftp.submit_pull_work("/home/username/temp/rumenz.img", # 远程文件"/Users/username/rumenz.img", # 本地路径文件,需要带上文件名call_bak_fun=(_file_pull_complete, ("rumenz.img",)) # 文件上传完成回调,第一个元素为方法,第二个是入参)# 列出文件列表files = sftp.listdir_attr("/home/baiyang")for f in files:print(f)# 开启交互回话session = sftp.open_pty_session("\$")# 发送单条命令session.send("cd ~/123")# # 发送单条命令并等待获取_ending_char符号(结束符支持el)session.send("scp test.txt username@130.16.16.133:~/\r", "Password:|yes/no")# # 当最后一行为yes/no 则执行yes,如果是Password则输入密码session.exp(("yes/no", "yes\r",("Password:", "xxx\r")),("Password:", "xxx\r"))# scp方式2'''伪代码if (yes/no):send yesif (Password:)send 密码elif (Password:)send 密码'''session.exp(("\$", "scp test.txt username@130.16.16.133:~/\r", # 期望$,并发送scp命令(("yes/no", "yes\r", ( # 如果返回yes/no,则发送yes"Password:", "xxx\r")), # 发送yes后,如果返回Password:结尾,则发送密码("Password:", "xxx\r") # 如果返回的是Password:结尾,则发送密码)))# 销毁session.destroy()sftp.destroy()# 支持通过with的方式使用SFTPMultipleClient,这样不需要显示的调用 sftp.destroy()with SFTPMultipleClient(host="130.16.16.18", port=22, username="baiyang", pwd="xxx") as sftp:# 列出文件列表files = sftp.listdir_attr("/home/baiyang")for f in files:print(f)if __name__ == '__main__':__example()相关文章:
python3实现类似expect shell的交互式与SFTP的脚本
前面写过一篇关于python实现类似expect shell的交互式能力的文章,现在补全一下加上sftp的能力脚本。 例子在代码中__example()方法。 依赖paramiko库,所以需要执行pip install paramiko来安装。 import os import queue import re import threading im…...
java游戏制作-飞翔的鸟游戏
一.准备工作 首先创建一个新的Java项目命名为“飞翔的鸟”,并在src中创建一个包命名为“com.qiku.bird",在这个包内分别创建4个类命名为“Bird”、“BirdGame”、“Column”、“Ground”,并向需要的图片素材导入到包内。 二.代码呈现 pa…...
NodeMCU ESP8266构建Web Server网页端控制设备
NodeMCU ESP8266构建Web Server网页端控制设备 前言 NodeMCU ESP8266 内部集成了TCP/IP协议栈,可以快速构建网络功能,搭建联网应用的硬件平台; ESP8266可以作为WiFi接入点(Station),这样可以方便连接互联…...
搭建区块链
参考B站FISCO BCOS(十八) java SDK与区块链交互_哔哩哔哩_bilibili 林中有神君 一、搭建第一个区块链网络 根据官方文档搭建:搭建第一个区块链网络 — FISCO BCOS v2.9.0 文档 (fisco-bcos-documentation.readthedocs.io) 使用javajdk 控制台2.6之后 本处是2.9.2…...
Python通过selenium调用IE11浏览器报错解决方法
前提 正常安装Python 工具,selenium 包可以正常导入。IE浏览器驱动 IEDriverServer.exe 已经正确放置到已经添加path目录的文件下。 报错现象: 解决方法 打开浏览器进入 internet 选项 切换到安全页签 ,去除“应用保护模式” 再次调用验证…...
Ubuntu 1.84.2Visual Studio Code 下载配置与vscode查看内存Hex Editor插件,简单易懂
目录 前言 一 首先我为啥要重装Vs Code呢? 二 下载1.84.2Visual Studio Code 三 配置Vscode终端字体 四 安装插件 前言 这是一篇将老版本的VsCode下载至最新版的博文,从下载到调试全篇 一 首先我为啥要重装Vs Code呢? 因为我想安装这个…...
opencv-图像金字塔
图像金字塔是一种图像处理技术,它通过不断降低图像的分辨率,形成一系列图像。金字塔分为两种类型:高斯金字塔和拉普拉斯金字塔。 高斯金字塔(Gaussian Pyramid): 高斯金字塔是通过使用高斯滤波和降采样&a…...
字符串匹配算法——KMP
有文本串aabaabaaf,模式串aabaaf问文本串中是否出现过模式串 暴力解法 最不用动脑子的,直接两层for循环,逐个匹配,匹配到不相等的值时把文本串后移一位,再重新比较。这种方法的复杂度是O(mn),该方法低效的…...
电子学会C/C++编程等级考试2023年03月(一级)真题解析
C/C++等级考试(1~8级)全部真题・点这里 第1题:字符长方形 给定一个字符,用它构造一个长为4个字符,宽为3个字符的长方形,可以参考样例输出。 时间限制:1000 内存限制:65536输入 输入只有一行, 包含一个字符。输出 该字符构成的长方形,长4个字符,宽3个字符。样例输入…...
微信小程序汽车租赁系统
微信小程序汽车租赁系统 本系统包含了3类用户,分别为客户、员工以及管理员,客户主要是满足自身的租车需求,员工主要负责车辆的调度问题和维修状况,管理员则是主要对人员、车辆和订单的管理。以下是对各自功能的详细介绍: 客户可…...
docker部署微服务
目录 docker操作命令 镜像操作命令 拉取镜像 导出镜像 删除镜像 加载镜像 推送镜像 部署 pom文件加上 在每个模块根目录加上DockerFile文件 项目根目录加上docker-compose.yml文件 打包,clean,package 服务器上新建文件夹 测试docker-compo…...
统计voc格式数据中的xml标签、bndbox到excel表格中
有这么个需求是将xml的内容: 1,filename 2.label 3.bndbox:xmin,xmax,ymin,ymax。 … 将这些东西写入excel表格中,方便我统计标签数量和框的分布! 于是撰写了脚本:xml2csv.py 我的xml文件形式如下。大家的目标检测格式大同小异! <annotation><folder>UAV_d…...
51单片机利用I/O口高阻状态实现触摸控制LED灯
51单片机利用I/O口高阻状态实现触摸控制LED灯 1.概述 这篇文章介绍使用I/O口的高阻状态实现一个触摸控制LED灯亮灭的实验。该实验通过手触摸P3.7引脚,改变电平信号控制灯的亮灭。 2.实验过程 2.1.实验材料 名称型号数量单片机STC12C20521LED彩灯无1晶振12MHZ1电…...
自动驾驶术语汇总
目录 智驾级别芯片相关自动驾驶相关辅助驾驶相关预警相关传感器相关泊车相关安全相关车灯相关 智驾级别 L0-L2属于辅助驾驶,L4-L5才算自动驾驶 L0(Level 0):无自动化。这是大多数传统汽车的级别,所有的驾驶任务都需要…...
Jsonpath - 数据中快速查找和提取的强大工具
JSON(JavaScript Object Notation)在现代应用程序中广泛使用,但是如何在复杂的JSON数据中 查找和提取所需的信息呢? JSONPath是一种功能强大的查询语言,可以通过简单的表达式来快速准确地定位和提取JSON数据。本文将介…...
java中,通过替换word模板中的关键字后输出一个新文档
一、要用到的jar包 我已上传了相关的jar包,需要的可以通过以下链接直接下载: https://download.csdn.net/download/qq_27387133/88558034 具体jar包截图: 二、实现的代码 注意:文件要用docx格式!!! word变量替换的方法&#…...
MySQL数据库约束你真的懂吗?
✏️✏️✏️今天给各位带来的是关于数据库约束方面的知识 清风的CSDN博客 😛😛😛希望我的文章能对你有所帮助,有不足的地方还请各位看官多多指教,大家一起学习交流! 动动你们发财的小手,点点关…...
YOCTO 下载repo工具失败解决办法
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o repocp repo ~/binchmod ax ~/bin/repo如果使用时报错, 切换ubuntu 到 python3 版本。gedit repo 修改repo默认链接地址:REPO_URL "https://gerrit.googlesource.com/git-repo"…...
github连接失败Host key verification failed.解决方案
问题描述 之前一直用的gitee协同协作,然后再最近一次云计算项目中团队使用的是github进行协作,但是按照常规步骤再GitHub上配置了ssh密钥后,却依然显示连接失败,无法推送和拉取代码,克隆仓库也是报错拒绝。具体报错信…...
【TIDB】TiDB认证考试PTCA 练习题 题库
目录 题目 答案 解析 题目 1.下列功能是由 TiKV 或 TiFlash 实现的为?( 选 2 项 ) A. 根据集群中 Region 的信息,发出调度指令 B. 对于 OLAP 和 OLTP 进行业务隔离 C. 将关系型数据转化为 KV 存储进行持久化 D. 将 KV 存储…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
