查看文本文件以查找特定文本并插入SQL

时间:2015-04-30 12:05:03

标签: sql-server powershell

我正在尝试优化我的Powershell脚本。 我有很多日志(文本)文件,我需要搜索特定文本条目的内容。 如果找到该条目,我需要使用sql数据库的插入触发脚本。

这就是我现在所拥有的:

$tidnu = (Get-Date -f dd.MM.yyyy)
$Text = "ERROR MESSAGE STACK"
$PathArray = @()
$NodeName = "SomeName"
$Logfil = "SomeLogFile"

Get-ChildItem $Path -Filter "*ORA11*.log" |
Where-Object { $_.Attributes -ne "Directory"} |
  ForEach-Object {
     If (Get-Content $_.FullName | Select-String -Pattern $Text)
     {
        $PathArray += $_.FullName
        $cmd.commandtext = "INSERT INTO ErrorTabel (Datotid, Nodename, Logfil, ErrorFound) VALUES('{0}','{1}','{2}','{3}')" -f $tidnu, $NodeName, $Logfil, "Yes"
        $cmd.ExecuteNonQuery()
     }
     else
     {                      
        $cmd.commandtext = "INSERT INTO ErrorTabel (Datotid, Nodename, ErrorFound) VALUES('{0}','{1}','{2}')" -f $tidnu, $NodeName, "No"
        $cmd.ExecuteNonQuery()
     }
  }

这工作正常,但是当我需要移动到另一个日志文件名时,我只是使用不同的输入再次使用相同的代码。 我想做的是使用一个数组和一个foreach循环,所以我可以在一个数组中指定所有日志文件,如:

$LogArray = @(Log1.log, log2.log, log3.log)

并指定所有Nodenames,如:

$NodeArray = @(Node1, Node2, Node3)

然后创建一个foreach循环,逐个遍历日志文件并插入数据库,每次循环运行时都匹配nodename。

有人可以帮助我实现这一目标吗?我知道应该怎么做,但我无法弄清楚如何编写代码。非常感谢所有帮助。

编辑:

好的,这就是我现在所拥有的,但我不确定它是否正确放在一起。它给了我一些奇怪的结果。

$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Data Source=PCDK03918;Initial Catalog=Rman;Integrated Security=SSPI;"
$conn.open()
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.connection = $conn

$tidnu = (Get-Date -f dd.MM.yyyy)
$Path = "C:\RMAN"
$Text = "ERROR MESSAGE STACK"


$nodes = @{
  'NodeName1' = 'Node1log1.log', 'Node1log2.log', 'Node1log3.log'
  'NodeName2' = 'Node2log1.log', 'Node2log2.log'
}

foreach ($NodeName in $nodes.Keys) {
foreach ($Logfil in $nodes[$NodeName]) {


Get-ChildItem $Path -Filter "*.log" |

ForEach-Object {
 If (Get-Content $_.FullName | Select-String -Pattern $Text)
 {       
    $cmd.commandtext = "INSERT INTO Error (Datotid, Nodename, Logfil, Error) VALUES('{0}','{1}','{2}','{3}')" -f $tidnu, $NodeName, $Logfil, "Yes"
    $cmd.ExecuteNonQuery()
 }
 else
 {                      
    $cmd.commandtext = "INSERT INTO Error (Datotid, Nodename, Logfil, Error) VALUES('{0}','{1}','{2}','{3}')" -f $tidnu, $NodeName, $Logfil, "No"
    $cmd.ExecuteNonQuery()
   }
  }  
 }
}
$conn.close()

我创建了$ nodes中提到的日志文件,在文件夹中,并将“ERROR MESSAGE STACK”放入Node1log1.log和Node1log2.log其余的日志文件里面没有“ERROR MESSAGE STACK”。

但是数据库中的结果很奇怪。它说Error = Yes来记录里面没有“ERROR MESSAGE STACK”的文件,并且对于相同的日志文件,某些行向下显示Error = No。加上它插入双行,所有这一切都没有按预期进行。

可能是因为我的

Get-ChildItem $Path -Filter "*.log" |

使用* .log?

是错误的

或者我对此完全错了?

再次编辑:

不确定昨天我在想什么,但我相信我现在已经解决了。

Get-ChildItem $Path -Filter "*.log" |

当然不行。

Get-ChildItem $Path -Filter $logfil |

更有意义,现在我的数据库输出看起来更正确。

@Ansgar Wiechers - 感谢您指点我正确的方向。我从中学到了很多东西。

1 个答案:

答案 0 :(得分:0)

考虑使用散列表:

$logs = @{
  'Log1.log' = 'Node1'
  'Log2.log' = 'Node2'
  'Log3.log' = 'Node3'
}

这样你可以像这样迭代日志:

foreach ($Logfil in $logs.Keys) {
  $NodeName = $logs[$Logfil]
  ...
}

如果每个节点名称有多个日志文件,则反转映射并将日志文件名存储在数组中会更有效:

$nodes = @{
  'Node1' = 'Log1.log', 'Log2.log', 'Log3.log'
  'Node2' = 'Log4.log', 'Log5.log'
}

然后您可以使用嵌套循环处理日志文件,如下所示:

foreach ($NodeName in $nodes.Keys) {
  foreach ($Logfil in $nodes[$NodeName]) {
    ...
  }
}

您应该能够将管道装入任何一个循环而无需进一步修改。

编辑:作为优化,您可以执行类似的操作,以避免在外部循环的每次迭代中出现不必要的fetchin日志:

$logs = Get-ChildItem $Path -Filter '*.log'

foreach ($NodeName in $nodes.Keys) {
  $logs | ? { $nodes[$NodeName] -contains $_.Name } | % {
    ...
  }
}