11 powershell sql-server-2012 windows-server
我在未运行的 SQL 代理作业步骤中设置了以下代码。收到的消息很简单:
无法开始执行第 1 步(原因:第(46)行:语法错误)。步骤失败。
工作的持续时间是: 00:00:00
此脚本的第 46 行是here-string
:
,@DriveLetter = '$($c.DriveLetter)'
Run Code Online (Sandbox Code Playgroud)
此脚本在 SQL Server 代理之外完美运行。
服务器名称表:
CREATE TABLE ServerTable (
ServerName varchar(50)
)
Run Code Online (Sandbox Code Playgroud)
磁盘空间表类似于:
CREATE TABLE DiskSpace (
ID int IDENTITY(1,1),
ServerName varchar(50),
DriveLetter varchar(2),
DiskSpaceCapacityGB decimal(12,5),
DiskSpaceFreeGB decimal(12,5)
)
Run Code Online (Sandbox Code Playgroud)
PowerShell 脚本:
This command is to allow SQL Agent job to show failure in event PowerShell script errors
Default behavior in SQL Agent for PowerShell steps it 'Continue'
$erroractionpreference = "Stop"
$sqlInstance = 'server1'
$sqlDatabase = 'database1'
$qServerList = @"
Select ServerName From ServerTable
"@
$srvList = Invoke-Sqlcmd -ServerInstance $sqlInstance -Database $sqlDatabase -Query $qServerList |
Where-Object {$_ -ne '' -or $_ -ne $null} | Select-Object -ExpandProperty ServerName
foreach ($s in $srvList)
{
if (Test-Connection -ComputerName $s -Count 1 -ErrorAction 'SilentlyContinue')
{
try
{
$cServer = Get-WmiObject Win32_Volume -ComputerName $s -ErrorAction 'Stop' |
where {$.DriveType -eq 3 -and $.DriveLetter } |
Select-Object @{Label="ServerName";Expression={$s}},
@{Label="DriveLetter";Expression={$.DriveLetter}},
@{Label="DiskSpaceCapacityGB";Expression={"{0:N0}" -f($.Capacity/1GB)}},
@{Label="DiskFreeSpaceGB";Expression={"{0:N2}" -f($_.FreeSpace/1GB)}}
foreach ($c in $cServer)
{
$qAddServerDiskSpace = @"
Run Code Online (Sandbox Code Playgroud)
EXEC [dbo].[StoredProcInsert]
@ServerName = '$($c.ServerName)'
,@DriveLetter = '$($c.DriveLetter)'
,@DiskSpaceCapacityGB = $($c.DiskSpaceCapacityGB)
,@DiskFreeSpaceGB = $($c.DiskFreeSpaceGB)
"@
try
{
Invoke-Sqlcmd -ServerInstance $sqlInstance -Database $sqlDatabase -Query $qAddServerDiskSpace -ErrorAction 'Stop'
}
catch
{
$ErrorMsg = $_.Exception.Message
$fullMsg = "Error writing executing dbo.StoredProcInsert for $s - $ErrorMsg"
Return $fullMsg
}
}
}
catch
{
$ErrorMsg = $_.Exception.Message
$qAddPSErrorLog = @"
Run Code Online (Sandbox Code Playgroud)
EXEC [dbo].[StoredProcInsert_Error]
@ServerName = '$($cServer.ServerName)'
, @ErrorText = '$($ErrorMsg)'
"@
try
{
Invoke-Sqlcmd -ServerInstance $sqlInstance -Database $sqlDatabase -Query $qAddPSErrorLog -ErrorAction 'Stop'
}
catch
{
$ErrorMsg = $_.Exception.Message
$fullMsg = "Error writing executing dbo.StoredProcInsert_Error for $s - $ErrorMsg"
Return $fullMsg
}
}
}
else
{
$qAddPSErrorLog = @"
EXEC [dbo].[StoredProcInsert_Error]
@ServerName = '$($cServer.ServerName)'
, @ErrorText = 'Unable to ping server'
"@
try
{
Invoke-Sqlcmd -ServerInstance $sqlInstance -Database $sqlDatabase -Query $qAddPSErrorLog -ErrorAction 'Stop'
}
catch
{
$ErrorMsg = $_.Exception.Message
$fullMsg = "Error writing executing dbo.StoredProcInsert_Error for $s - $ErrorMsg"
Return $fullMsg
}
}
Run Code Online (Sandbox Code Playgroud)
}
Run Code Online (Sandbox Code Playgroud)
编辑
设置附加步骤以尝试使用 CmdExec 类型作为PowerShell -Command "& { }"
. 执行此操作后,脚本会运行,并为相应的 catch 块填充错误日志,但不会将磁盘空间数据写入表中。
此运行的代理历史记录显示警告消息:
消息以用户身份执行:NT Service\SQLAgent$myInstance。警告:一些导入的命令名称包含未经批准的动词,这可能会使它们不易被发现。使用 Verbose 参数获取更多详细信息,或键入 Get-Verb 以查看批准的动词列表。处理退出代码 0。该步骤成功。
如果我使用相同类型的步骤但调用该文件:PowerShell -File MyScript.ps1
我收到与上面的 PowerShell 步骤类型相同的语法错误消息。
小智 12
这不是很直观,我从来没有找到任何具体的解释[例如没有找到确切的 BOL 或白皮书]。
SQL 代理作业中的语法错误是基于用户令牌的 T-SQL 语法错误。所以这基本上意味着 PowerShell 子表达式运算符被视为 SQL Server 代理的令牌。因此,在 PowerShell 中,这$( )
似乎被视为 SQL Server 代理的保留字符序列。因此,SQL代理会寻找类似从BOL文章中引用这个T-SQL例如:
PRINT N'Current database name is $(A-DBN)' ;
。
所以在我的脚本中,当它到达时,@DriveLetter = '$($c.DriveLetter)'
,“$c.DriveLetter”不是允许的标记之一。
解决方法是在 PowerShell 中不使用子表达式语句。我会在我的脚本中进行调整,这样:
$qAddServerDiskSpace = @"
EXEC [dbo].[StoredProcInsert]
@ServerName = '$($c.ServerName)'
,@DriveLetter = '$($c.DriveLetter)'
,@DiskSpaceCapacityGB = $($c.DiskSpaceCapacityGB)
,@DiskFreeSpaceGB = $($c.DiskFreeSpaceGB)
"@
Run Code Online (Sandbox Code Playgroud)
将不得不修改为这样的东西:
$severName = $c.ServerName
$driveLetter = $c.DriveLetter
$capacityGB = $c.DiskSpaceCapacityGB
$freeGB = $c.DiskFreeSpaceGB
$qAddServerDiskSpace = @"
EXEC [dbo].[StoredProcInsert]
@ServerName = '$serverName'
,@DriveLetter = '$driveLetter'
,@DiskSpaceCapacityGB = $CapacityGB
,@DiskFreeSpaceGB = $freeGB
"@
Run Code Online (Sandbox Code Playgroud)
对我的脚本进行了上述调整,现在它可以完美运行。
归档时间: |
|
查看次数: |
7367 次 |
最近记录: |