AWS Lambda中Paramiko执行SSH命令间歇性超时问题求助
在AWS Lambda中使用Paramiko时遇到间歇性超时问题:调用ssh函数时会随机超时,但把命令改成pwd再改回原命令后,函数又能正常返回结果。本地测试这段代码完全正常,Lambda已配置在能SSH到目标主机的正确VPC和安全组内,且未超出内存限制。有没有忽略的明显问题?
代码实现
class fileFinder: _uname = None _password = None def __init__(self, secret, params) -> None: self._uname = secret["uname"] self._password = secret["password"] self.params=params def ssh(self): try: client = SSHClient() client.set_missing_host_key_policy(AutoAddPolicy()) client.connect(hostname="myhost", username=self._uname, password=self._password) stdin, stdout, stderr = client.exec_command(' cd /my/cool/pathway; find ./ -name "PREFIX*.hst" -newerct "2023-09-01T00:00" -not -newerct "2023-10-01T11:09"') output = stdout.read().decode("utf8") return self.buildResponse(output) except Exception as error: print("there was an error" + repr(error)) def buildResponse(self, stdout) : fileList: list[str] = [] currFname: str = "" for i in range(len(stdout)): if stdout[i] == "." and stdout[i+1] == "/" or stdout[i] == "/" : continue elif stdout[i] == "\n": fileList.append(currFname) currFname = "" else: currFname += stdout[i] return {"logs" : fileList}
错误信息
{ "errorMessage": "2023-10-02T18:14:32.828Z 7b520d57-bc32-49b6-8da7-653c24a1bfe5 Task timed out after 20.02 seconds" }
命令执行时间过长
你的find命令可能在某些场景下需要遍历大量文件,执行时间超过Lambda默认的20秒超时阈值。pwd这类轻量命令不会触发超时,但原命令在文件数量多的时候就会超时。
解决:调整Lambda函数的超时时间(最大可设15分钟),同时优化find命令——比如缩小搜索路径、添加-type f限定只查找文件、增加更精确的过滤条件,减少遍历范围。未正确关闭SSH连接
代码中没有显式关闭SSH客户端连接,Lambda的执行环境可能会复用旧连接,导致后续调用出现资源占用或连接异常,引发间歇性超时。
解决:在try/finally块中添加连接关闭逻辑,确保每次调用后释放资源:def ssh(self): client = None try: client = SSHClient() # 现有连接、命令执行逻辑... except Exception as error: print("there was an error" + repr(error)) finally: if client is not None: client.close()Lambda资源限制
Lambda的CPU资源与内存配额绑定,内存配置较低时,CPU性能也会受限。如果find命令需要大量CPU计算,可能在冷启动或资源不足时超时。
解决:适当提高Lambda的内存配置,同时确认是否有其他进程抢占资源。目标主机负载波动
目标主机在某些时段CPU、IO负载过高,导致find命令执行缓慢,进而引发Lambda超时。
解决:检查目标主机的监控数据,确认是否存在时段性负载高峰;也可以给find命令添加优先级调整,比如nice -n 10 find ...,降低对主机资源的影响。stdout读取阻塞
如果find命令产生大量stderr输出,只读取stdout会导致缓冲区满,进而阻塞进程。
解决:同时读取stderr输出,避免缓冲区阻塞:stdout_output = stdout.read().decode("utf8") stderr_output = stderr.read().decode("utf8") # 可打印stderr输出排查问题
内容的提问来源于stack exchange,提问作者Squid

