Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
0 Kudos

作者:shawn.penner,现就职于SAP

原文地址(英语)

Cleaning up Orphaned Files

过去的时间里,已经有一些问题和漏洞会在产生垃圾文件,存放于输入/输出文件资源服务器上(FRS)。这个页面里的脚本旨在创建一个清理FRS服务器的工具,来保证不产生多余的文件来占用空间。

所有的这些脚本都是用VBScript编写的,而且为了BOE XI R2设计,但是一般来讲,它们也会在BOE XI R3上面生效。(尽管他们在BOE XI R3上不被支持)

注意:

更多其他的脚本和信息,关于如何运行脚本,可以在这里找到:

Scripts and Samples

扫描和清理FRS服务器

这个脚本将会对输入和输出的FRS里面无响应的文件进行扫描,并且删除它们。它同样会删除文件移除后残留的文件夹。它运作的方法是,如果一个相对应的InfoObject存在,假设最低级别的文件夹名字就是这个对象的SI_ID。如果这个有SI_ID的对象存在于Enterprise Server里面,那么这个对象就被假定为有效。

注意事项:

  • 您需要将用户名,密码,CMS名字都改成特别对应于您的企业服务器的值。强烈建议您使用管理员账户,因为其他用户可能不会看到所有企业服务器上面的对象。而且如果脚本看不到对象,它就会假设它不存在,然后删除符合的文件。
  • 这个脚本会创建一个日志文件,位于"C:\output.log" 来储存脚本运行的结果。
  • 为了在测试模式下运行这个脚本,把DoDelete变量设置为false。要是想脱离测试模式,把DoDelete变量设置为true
  • 这个脚本必须在FRS实际存放的服务器上运行,或者那里有一个直接的路径通到FRS文件夹。
  • 你将会需要把输出和输入FRS改成根目录。

     XI R2的默认位置:

          "C:\Program Files\Business Objects\BusinessObjects Enterprise 11.5\FileStore\Input"

          "C:\Program Files\Business Objects\BusinessObjects Enterprise 11.5\FileStore\Output"

     XI R3的默认位置:

          "C:\Program Files (x86)\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Input"

          "C:\Program Files (x86)\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Output"

  • 输入和输出的FRS的路径必须不能在结尾加入斜线,否则脚本会失效。
  • 如果你在一个64位操作系统例如Windows 7上运行该脚本,你会需要检验这个脚本的32位版本是否能够运行。否则你会遇到报错: "ActiveX component can't create object: 'CrystalEnterprise.SessionMgr' "

     例如:%windir%\SysWOW64\cscript.exe scanfrs.vbs

扫描和清理FRS服务器

Dim DoDelete
Dim inputFRSRoot
Dim outputFRSRoot

DoDelete = False   ' False = Test Mode, True = Actually Delete the Files
inputFRSRoot = "C:\Program Files (x86)\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Input"
outputFRSRoot = "C:\Program Files (x86)\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Output"

'Declare CMS logon variables
Dim CMS
Dim Usnername
Dim Password
Dim Authtype

CMS = "localhost"
Username = "Administrator"
Password = ""
Authtype = "secEnterprise"

'Declare variables for Enterprise Session
Dim oEnterpriseSessionMgr
Dim ceSession
Dim oInfoObjects
Dim oInfoObjects2
Dim boServer1Admin
Dim boServer2Admin

' File IO stuff
Dim objFSO
Dim outputFile

'Open the outputFile for logging.
Set objFSO = CreateObject("Scripting.FileSystemObject")
set outputFile = objFSO.OpenTextFile("C:\output.log",8,True)

outputFile.WriteLine("-------- Starting Script --------")

'Load the Enterprise Session Manager
Set oEnterpriseSessionMgr = CreateObject("CrystalEnterprise.SessionMgr")

'Logon to the CMS and create iStore object
Set ceSession = oEnterpriseSessionMgr.Logon(Username, Password, CMS, Authtype)
Set iStore = ceSession.Service("","InfoStore")

outputFile.WriteLine("Input FRS Root = " & inputFRSRoot)
outputFile.WriteLine("Output FRS Root = " & outputFRSRoot)

' Now that we have the root folders - we need to loop through them and drill down to the deepest level
' The logic used is:
' - Is there a file?  If not, is there a sub-folder.
' - If there is a sub-folder - then go into it
' - If there is a file - then look at the last folder name - that will be the SI_ID
' - Check if an object with that SI_ID exists.  If it does - all is well - if not - flag for deletion
' - The deletion will go up folder by folder until one of three conditions occur. 
' - 1. A file exists in the folder.
' - 2. More than 1 sub-folder
' - 3. The name of the current folder is either Input, or Output

Dim finalOutput
Dim finalInput

' Scan the Input FRS
outputFile.WriteLine("Starting Input FRS")
finalInput = CheckAndDelete(DoDelete, iStore, objFSO, outputFile, inputFRSRoot)
outputFile.WriteLine("")

' Scan the Output FRS
outputFile.WriteLine("Starting Output FRS")
finalOutput = CheckAndDelete(DoDelete, iStore, objFSO, outputFile, outputFRSRoot)

outputFile.WriteLine("All Done")

' Clean everything up
outputFile.close
ceSession.Logoff()
Set oInfoObjects = Nothing
Set oInfoObject = Nothing
Set iStore = Nothing
Set ceSession = Nothing
Set oEnterpriseSessionMgr = Nothing


Function CheckAndDelete(DoDelete, iStore, objFSO, outputFile, fileRoot)
Dim boFolder
Dim boFile
Dim folderCount
Dim fileCount
Dim boSubFolder
Dim DeleteThisFolder
Dim boInfoObjects

' Set it initially to not delete the folder
CheckAndDelete = false

Set boFolder = objFSO.GetFolder(fileRoot)

' Get a count of the files in this folder, and a count of the sub-folders
fileCount = boFolder.Files.Count

' Are there files here - then we need to check if the matching SI_ID exists
if fileCount > 0 then
  Set boInfoObjects = iStore.Query("select SI_ID from CI_INFOOBJECTS, CI_SYSTEMOBJECTS, CI_APPOBJECTS where SI_ID = " & boFolder.Name)

  ' If the count is 0 - then this is an orphan
  if boInfoObjects.count = 0 then
   outputFile.WriteLine("Orphaned File with ID " & boFolder.Name & " found at " & fileRoot)
  
   ' Delete the files in this folder
   For Each boFile in boFolder.Files
    if DoDelete = True then
     outputFile.WriteLine("Deleting File: " & fileRoot & "\" & boFile.Name)
     objFSO.DeleteFile fileRoot & "\" & boFile.Name, true
    Else
     outputFile.WriteLine("In Test Mode - Would have deleted File: " & fileRoot & "\" & boFile.Name)
    End If
   Next

   ' Set the delete flag to true to tell the function one up the recursive stack to remove this folder
   CheckAndDelete = true
  end if
end if

For Each boSubFolder in boFolder.SubFolders
  'outputFile.WriteLine(boSubFolder.Name)
  DeleteThisFolder = CheckAndDelete(DoDelete, iStore, objFSO, outputFile, fileRoot & "\" & boSubFolder.Name)
 
  if DeleteThisFolder = true then
   if DoDelete = True then
    outputFile.WriteLine("Deleting Folder: " & fileRoot & "\" & boSubFolder.Name)
    objFSO.DeleteFolder(fileRoot & "\" & boSubFolder.Name)
   Else
    outputFile.WriteLine("In Test Mode - Would have deleted Folder: " & fileRoot & "\" & boSubFolder.Name)
   End If
 
   ' Now check and see if there are any more sub-folders in this folder - or if the name of the folder is Input or Output.
   folderCount = boFolder.SubFolders.Count
   if folderCount = 0 then
    if boFolder.Name = "Input" or boFolder.Name = "Output" then
     CheckAndDelete = false
    else
     CheckAndDelete = true
    end if
   end if
  end if
Next
End Function

解析RepoScan XML

接下来的脚本实际上没有使用BusinessObjectsSDK来清理输入和输出FRS。相反它利用了RepoScan工具来鉴定CMS数据库和磁盘上存放的不匹配情况。

注意事项:

  • 你需要运行RepoScan工具来生成一个日志文件。为了运行RepoScan,参照如下步骤:

          ·创建一个options.txt文件,我已经把一个示例贴在下面:

          -dbdriver mysqldatabasesubsystem

          -inputfrsdir "C:\Program Files\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Input"

          -outputfrsdir "C:\Program Files\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Output"

          -connect UID=sa;PWD=bopassword123;DSN=BOE120;HOSTNAME=MyEnterpriseServer;

          -outputdir c:\

          -repair false

上面的这些选项鉴别了:文件使用的什么数据库,输入和输出FRS保存位置,数据库连接字符串,生成的日志文件存放在哪里,是否要尝试和修复问题。

           ·一旦你生成了options.txt 文件,到下面的目录 C:\Program Files\Business Objects\BusinessObjects Enterprise 12.0\win32_x86 (For BOE XI R2)执行命令:

reposcan -optionsfile c:\options.txt

c:\options.txt就是配置文件所在的位置。

          ·这回生成一个日志文件,名为 "Repo_Scan_<Date and Time>.xml",它会生成在上面特定的输出目录下(在这里是C:\)。

  • 你会需要在脚本里面更改文件的路径,改成被RepoScan生成的xml文件位置。
  • 如果你在一个64位操作系统例如Windows 7上运行这个脚本,你会需要检验这个脚本的32位版本是否能够运行。否则你会遇到报错:"ActiveX component can't create object: 'Scripting.FileSystemObject' "

     例如:%windir%\SysWOW64\cscript reposcanxmlparser.vbs

解析RepoScan XML

Dim xmlDoc
Dim fname
Dim fpath
dim filesys

Set filesys = CreateObject("Scripting.FileSystemObject")
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.Async = "False"
xmlDoc.Load("C:\Documents and Settings\spenner\My Documents\xmlparse\Repo_Scan_2008_11_24_12_21_24.xml")

strQuery = "/ScanResults/File"
Set colItem = xmlDoc.selectNodes(strQuery)

For Each objItem in colItem
fname = objItem.selectSingleNode("File_Name").nodeTypedValue
fpath = objItem.selectSingleNode("Directory_Path").nodeTypedValue

WScript.Echo "Manually Deleting File: " + fpath + fname
filesys.DeleteFile fpath + fname, true

'WScript.Echo objItem.nodeName & ": " & objItem.text
Next