【发布时间】:2021-05-18 10:04:38
【问题描述】:
由于未知原因,服务器端 LotusScript 代理在尝试读取现有邮件归档文件的物理文件大小时抛出错误 53“找不到文件”。情况如下:
LS 代理正在循环服务器“\Data”目录下给定目录“\archive”中的所有文件。有问题的服务器是在 Windows 2016 服务器上运行的 Domino 10.0.1。
LS 代码循环目录查找名称遵循给定模式的数据库文件,例如“a_EmployeeID.nsf”。如果数据库的文件名符合模式,则代码使用文件名中的 EmployeeID 扫描服务器的 names.nsf 以查找存档所有者。如果没有找到该 ID 的人员文档,则代码会尝试使用 FileLen(filePath & FileName) 读取数据库的物理文件大小。然后将生成的数据(文件路径 + 文件大小)+ EmployeeID 写入磁盘上的报告文件。不遵循该模式的文件也至少会写回报告中。该代理背后的想法是找到“孤立”或放错位置的数据库。
对于大约 80% 的已扫描文件,这可以正常工作,具有精确文件大小的记录将写入报告。但是对于另外约 20% 的运行时间,error 53 "File not found" 会拉起。在这种情况下,记录只包含文件路径/名称 + EmployeeID(如果可用)+“-1”作为文件大小。因为该文件显然确实存在,所以我认为这是一个访问或安全问题。
代理使用管理员 ID 签名,该管理员 ID 对服务器和相关存档文件具有最大访问权限(策略 ID 在 dbs 的 ACL 中具有管理员访问权限)。 代理的安全设置设置为 3 级(具有完全管理员权限的无限制访问),因为我首先使用在服务器上具有完全管理员访问权限的 ID 对代理进行了签名(与现在使用的 ID 相同)。
比较数据库的 ACL,我找不到“有效”和无效的 ACL 之间的任何区别。不过,我看到的是,抛出这个错误的显然总是同一个数据库,所以这不是一个随机问题。
为了完整起见,这里是代理代码的关键部分:
sFileName = Dir$(sPath & "*.nsf")
Do Until sFileName = ""
iCount = iCount + 1
sEmpid = "" 'reset
lSizeArc = 0 'reset
dblSizeArc = 0 'reset
sSizeArcFmt = "" 'reset
If(sFileName Like sPattern) Then
sEmpid = Left(Right(sFileName, Len(sFileName) - 2), 6)
Set vec = vwEgid.Getallentriesbykey(sEmpid, True)
If(vec.count = 0) Then
On Error 53 Resume Next 'Error 53 ("File not found")
lSizeArc = FileLen(sPath & sFilename)
If(Err = 53) Then
lSizeArc = -1
sSizeArcFmt = "-1 (no size available)"
Err = 0
Else
dblSizeArc = Round((lSizeArc / 1024 / 1024), 3)
sSizeArcFmt = Format$(dblSizeArc, "0.000") & " MB"
End If
Print #iFileNum,_
"ORPHANED_ARCHIVE;" & sEmpid & ";" & sFileName & ";" & sSizeArcFmt
End If
Else
On Error 53 Resume Next 'Error 53 ("File not found")
lSizeArc = FileLen(sPath & sFilename)
If(Err = 53) Then
lSizeArc = -1
sSizeArcFmt = "-1 (no size available)"
Err = 0
Else
dblSizeArc = Round((lSizeArc / 1024 / 1024), 3)
sSizeArcFmt = Format$(dblSizeArc, "0.000") & " MB"
End If
Print #iFileNum,_
"BAD_FILE_PATTERN;NO_EGID;" & sFilename & ";" & sSizeArcFmt
End If
sFileName = Dir$() 'next file
Loop
在我开始转向不同的方向(例如研究使用 Windows shell 或 .dll 命令)之前,我真的很想了解为什么在某些情况下代码坚持认为无法“找到”所查看的某些文件。
有什么想法吗?
2021-05-19 更新
所以最后我找到了解决这种奇怪现象的方法(我承认,这并不是对我的编程技能的赞美): 再次查看抛出错误 53 的文件,我意识到它们都相当大,确切地说是 > 2.1 GB。所以我不得不承认我犯了一个愚蠢的编程错误:给一个 LONG 变量分配一个这样大小的值当然是行不通的。愚蠢的业余错误... (但是为什么代码没有像通常那样抛出正确的错误,告诉值超出限制?) 无论如何,所以我将变量更改为 DOUBLE。 但是:结果仍然相同,尽管 >> 错误 53。 然后再次查看设计师帮助我发现了这个小笔记:
FileLen 返回一个 Long 值
换句话说:FileLen 本身无法处理这么大的文件,并且在解释器发现我的错误编码之前显然会引发该错误。 换句话说:没有办法那样解决我的问题。回到@TorstenLink 的评论:我现在就用他的方法
非常奇怪的错误信息,不过,我想说...
感谢所有帮助我思考的人;)
【问题讨论】:
-
Domino 将数据库锁定在其访问范围内,以便在 Domino 之外进行访问。我永远不会尝试从文件系统中获取此类信息...为什么不使用 NotesDBDirectory?
-
是的,使用 NotesDBDirectory 是我最初的计划。但后来我意识到这个方法有 2 周的时间点: - #1 循环这个对象我无法控制要循环的文件夹。有问题的服务器拥有数万个数据库,但我只对 \archive 文件夹下的数据库感兴趣,它始终是整个服务器。 - #2 这个对象我只能访问数据库对象。如果它存储在正确的文件夹中,我必须查看它,然后它的文件名是否遵循给定的模式。如果两者都是这种情况,我必须打开数据库才能查看它的大小
-
和文件名中的特殊字符有关系吗?
-
NotesDBDirectory 是一个相当快的对象。除非您打开数据库,否则循环数千个数据库只需几秒钟(NotesDatabase- 通过 NotesDBDirectory 获得的对象未打开,您需要为您感兴趣的数据库调用 db.Open("", ""))。并且可以从关闭的对象中读取文件路径:
If Left( db.FilePath , 8 ) = "archive\" then。这将非常快,因为您只需要真正打开正确路径中的文件... -
@Duston - 不应该是个问题。该模式基本上是“a_EmpID.nsf”,其中 EmpId 是 6 个字符,以“E”开头,然后是第二个简单的 ASCII 字符(通常是 A 到 E),然后是 4 位数字。但仔细观察仍然是个好主意——也许有一些“看不见”的特殊字符。我会检查的
标签: lotus-notes lotus-domino lotusscript hcl-notes