AWS Lambda分层部署ClamAV扫描S3文件访问/tmp提示文件不存在
AWS Lambda集成ClamAV扫描S3文件提示/tmp路径下文件不存在问题排查
问题场景
在基于Lambda Layer分层部署的AWS Lambda中集成ClamAV杀毒引擎实现S3文件病毒扫描,执行逻辑为:
- 从S3存储桶下载待扫描对象
- 将文件写入Lambda运行环境的
/tmp目录 - 启动
clamscan进程对目标文件执行扫描
进程启动时抛出错误:指定位置未找到文件(对应路径为/tmp/{s3Object.Key})
核心实现代码如下:
var s3Object = await _amazonS3Client.GetObjectAsync(s3Event.Bucket.Name, s3Event.Object.Key); if (!s3Object.WithScanStatus(ObjectScanStatus.InProgress)) { _logger.LogWarning(@$"Trying to scan already processed asset. Name: {s3Event.Object.Key}. Bucket: {s3Event.Bucket.Name}"); return s3Object.GetScanStatus(); } using (var fileStream = new FileStream($"/tmp/{s3Object.Key}", FileMode.Create, FileAccess.Write)) { s3Object.ResponseStream.CopyTo(fileStream); } var process = new Process { StartInfo = new ProcessStartInfo { FileName = "clamscan", Arguments = $" --database=/opt/var/lib/clamav/ /tmp/{s3Object.Key}", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true } }; process.Start();
排查思路与修复方案
- S3对象Key拼接本地路径的路径不存在问题
S3的Object Key支持/作为虚拟目录分隔符,也可包含特殊字符、空格。直接拼接/tmp/{s3Object.Key}作为本地文件路径时,如果Key包含层级(例如upload/2024/06/test.exe),会尝试写入/tmp/upload/2024/06/test.exe,但代码未提前创建多级父目录,FileStream创建文件时会因父目录不存在失败,后续clamscan自然无法找到对应文件。如果Key包含空格等特殊字符,未加引号包裹的路径传给clamscan时会被截断,也会报文件不存在。
修复方式:不要直接用S3 Key作为本地文件名,改用随机文件名存储到/tmp根目录,彻底规避路径层级问题;传参给clamscan时用引号包裹文件路径。参考代码:// 生成临时文件路径,避免Key带路径导致的父目录不存在问题 var localScanPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}{Path.GetExtension(s3Event.Object.Key)}"); using (var fileStream = new FileStream(localScanPath, FileMode.Create, FileAccess.Write)) { // 用异步拷贝方法,避免同步阻塞导致的流写入不完整 await s3Object.ResponseStream.CopyToAsync(fileStream); } // 传参给clamscan时给路径加双引号,避免特殊字符截断参数 Arguments = $"--database=/opt/var/lib/clamav/ \"{localScanPath}\"", - 流写入不完整、时序问题
原代码在async上下文中使用同步CopyTo方法拷贝流,未做写入完成校验,大文件场景下可能出现流未完全写入磁盘、FileStream未完成flush就被释放的情况,导致clamscan启动时文件还未生成完成。
修复方式:改用CopyToAsync并加await等待写入完成,启动进程前增加校验逻辑,判断本地文件是否存在、文件大小是否和S3对象的ContentLength一致,确认文件落盘后再启动扫描进程。 - Lambda运行环境限制问题
Lambda的/tmp目录默认配额为512MB(最高可配置到10GB),如果待扫描文件大小超过/tmp剩余空间,文件写入会失败,无法生成完整文件。另外需确认Lambda执行用户对/tmp目录下的文件有读权限,默认配置下权限是正常的,如果自定义Layer修改过目录权限需要调整。
排查方式:写入文件后打印本地文件路径、File.Exists()返回值、文件长度、/tmp目录剩余空间,确认文件正常写入。 - ClamAV启动参数与环境问题
原代码Arguments参数开头带多余前导空格,部分版本ClamAV可能出现参数解析异常;另外需确认Layer中ClamAV的病毒库路径/opt/var/lib/clamav/真实存在,避免ClamAV启动时报病毒库不存在的错误被误判为目标扫描文件不存在。
排查方式:先在Lambda中执行clamscan --version确认程序可正常运行,再传入一个打包在Layer中的固定测试文件验证扫描逻辑正常,最后接入动态S3文件下载逻辑。
内容的提问来源于stack exchange,提问作者IR Codder
相关产品推荐
相关产品推荐

