在 SQL Server 代理中執行 Powershell 腳本的執行策略錯誤
2014 年使用我的 AD 帳戶通過憑據從 SQL Server 代理執行 powershell 腳本。我收到以下錯誤。
作業步驟在 PowerShell 腳本的第 1 行收到錯誤。對應的行是“set-executionpolicy RemoteSigned -scope process -Force”。更正腳本並重新安排作業。PowerShell 返回的錯誤資訊是:‘Security error.
我在Google上的搜尋,沒有發現任何有用的東西。我可以在我的工作站上通過 SSMS 從 Powershell 控制台執行腳本,而不會出現任何問題。
執行策略設置為無限制
PS C:\WINDOWS\system32> Get-ExecutionPolicy Unrestricted
錯誤輸出中提到的行必須由 SQL Server 自動添加,因為
RemoteSigned -scope process -Force
它不在程式碼中的任何位置。除了使用 AD 帳戶執行作業之外,我還需要在 SQL Server 代理中設置什麼嗎?
這是來自的powershell行
msdb.dbo.syssubsystems
C:\Program Files (x86)\Microsoft SQL Server\120\Tools\Binn\SQLPS.exe
更新
這是版本
PS SQLSERVER:\SQL\CD000023\CEF_2014_1> $PSVersionTable.PSVersion Major Minor Build Revision ----- ----- ----- -------- 2 0 -1 -1
2015 年 1 月 3 日更新
此腳本基於中央管理伺服器的註冊伺服器創建表 serverlist。然後它連接到每個伺服器並辨識它正在偵聽的埠。
# connection parameters Param ( [string] $CMSServer="someuser\someinstance", # CMS server that stores serverlist [string] $CMSDatabase="msdb", # database where the serverlist is stored [string] $CMSUser="someuser", # username to connect to the cms server [string] $CMSPassword="somepassword", # password to connect with the cmsuser [string] $CMSTable="dbo.serverlist", # name of table that stores instances [string] $CMSTableNoSchema="serverlist", # name of table that stores instances [string] $UserName="remoteuser", # username to connect to each instance [string] $Password="remotepassword", # password to connect to each instance [string] $SrcDatabase="tempdb", # database where listening ports are stored [string] $SrcTable="#listeningport" # table where listening ports are stored ) # load in the SQL Server Powershell Module [System.Reflection.Assembly]::LoadWithPartialName( ` "Microsoft.SqlServer.Smo"); # log file function $logfile = "c:\temp\get_server_ports_$(get-date -format `"yyyy_MM_ddtt`").txt" # initalize log file $logfile | out-file -Filepath $logfile function log($string, $color) { if ($Color -eq $null) {$color = "white"} write-host $string -foregroundcolor $color $string | out-file -Filepath $logfile -append } # CMS Server connection $CMSServerConnectionString = "Data Source=$CMSServer;Initial Catalog=$CMSDatabase;User Id=$CMSUser;PWD=$CMSPassword;" $CMSServerConnection = new-object system.data.SqlClient.SqlConnection($CMSServerConnectionString); $CMSServerConnection.Open() # create SMO objects so that tables can be created and dropped $srv = new-Object Microsoft.SqlServer.Management.Smo.Server($CMSServerConnection) $db = New-Object Microsoft.SqlServer.Management.Smo.Database $db = $srv.Databases.Item($CMSDatabase) # drop and recreate the serverlist Table on the CMS server $tb = $db.Tables[$CMSTableNoSchema] IF ($tb) {$tb.Drop()} # Create the serverlist Table on the cms server $tb = new-object Microsoft.SqlServer.Management.Smo.Table($db, $CMSTableNoSchema) $col1 = new-object Microsoft.SqlServer.Management.Smo.Column($tb, "server_name", [Microsoft.SqlServer.Management.Smo.DataType]::NChar(255)) $col2 = new-object Microsoft.SqlServer.Management.Smo.Column($tb, "server_port", [Microsoft.SqlServer.Management.Smo.DataType]::Int) $tb.Columns.Add($col1) $tb.Columns.Add($col2) $tb.Create() # collect the list of servers $cmd4 = new-object System.Data.SQLClient.SQLCommand $cmd4.CommandText = " insert into msdb.dbo.serverlist (server_name, server_port) select server_name, 1 from msdb.dbo.sysmanagement_shared_registered_servers_internal " $cmd4.Connection = $CMSServerConnection $rowsInserted = $cmd4.ExecuteNonQuery() # Create a Dataset to hold the DataTable from server_list $dataSet = new-object "System.Data.DataSet" "ServerListDataSet" $query = "SET NOCOUNT ON;" $query = $query + "SELECT server_name " $query = $query + "FROM $CMSDatabase.$CMSTable where server_name not in( select server_name from $CMSDatabase.dbo.excludeServerList )" # Create a DataAdapter which you'll use to populate the DataSet with the results $dataAdapter = new-object "System.Data.SqlClient.SqlDataAdapter" ($query, $CMSServerConnection) $dataAdapter.Fill($dataSet) | Out-Null $dataTable = new-object "System.Data.DataTable" "ServerList" $dataTable = $dataSet.Tables[0] # for each server $dataTable | FOREACH-OBJECT { Try { #write-host "server_name: " $_.server_name log "server_name : $ServerBConnectionString" yellow $ServerBConnectionString = "Data Source="+$_.server_name+";Initial Catalog=$SrcDatabase;User Id=$UserName;PWD=$Password" #write-host "ServerBConnection: " $ServerBConnectionString $ServerBConnection = new-object system.data.SqlClient.SqlConnection($ServerBConnectionString); $ServerBConnection.Open() # create SMO objects so that tables can be created and dropped $srv = new-Object Microsoft.SqlServer.Management.Smo.Server($ServerBConnection) $db = New-Object Microsoft.SqlServer.Management.Smo.Database $db = $srv.Databases.Item($SrcDatabase) # collect port number from server $cmd3 = new-object System.Data.SQLClient.SQLCommand $cmd3.CommandText = " SELECT @@SERVERNAME as servername, cast(CONNECTIONPROPERTY('local_tcp_port') as int) AS port INTO $SrcTable " $cmd3.Connection = $ServerBConnection $rowsInserted = $cmd3.ExecuteNonQuery() # get port number from table $cmd2 = new-object System.Data.SQLClient.SQLCommand $cmd2.CommandText = "SELECT port FROM $SrcTable" $cmd2.Connection = $ServerBConnection $port = [Int32]$cmd2.ExecuteScalar() #write-host "port: " $port log "port: $port" yellow # update cms table $cmd = new-object System.Data.SQLClient.SQLCommand $cmd.CommandText = "UPDATE $CMSDatabase.$CMSTable SET server_port = $port WHERE server_name = '"+$_.server_name+"'" #write-host "success: " $cmd.CommandText $cmd.Connection = $CMSServerConnection $rowsUpdated = $cmd.ExecuteNonQuery() log "success: $_.server_name" green #write-host "success: " $_.server_name $ServerBConnection.Close() } Catch [System.Exception] { $ex = $_.Exception #write-host "failure: " $ex.Message " on server " $_.server_name log "failure: $ex.Message on server $_.server_name" red #Write-Host $ex.Message } Finally { #write-host "server_name: " $_.server_name } } $CMSServerConnection.Close()
您收到的錯誤實際上已在連接項中註明,但 Microsoft 將其顯示為
closed won't fix
. 此連接項中缺少的事實是子系統SQLPS
是通過系統資料庫項設置的。我不知道何時何地實際設置了這一點。此系統資料庫項位於下面的路徑中,並且在我的本地框中設置為
RemoteSigned
. 現在我通常不建議更改系統資料庫項,但您可以嘗試將其更改為RemoteSigned
,您可能會發現您的腳本將無錯誤地執行。可能需要重啟 SQL Agent 服務,不知道。
HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.SqlServer.Management.PowerShell.sqlps120
現在,通過使用,
Unrestricted
您實際上可以使腳本在執行 PowerShell 腳本時收到提示。這可能是實際產生錯誤的原因,因為 SQL 代理無法響應提示或不知道如何處理它。確實沒有理由使用該策略設置,因為該策略RemoteSigned
足以允許您在伺服器上編寫和設置的腳本在沒有提示的情況下執行。我會,除非您深入了解返回的完整錯誤,否則它可能包含類似於以下消息的文本。這是您在將執行策略設置為時收到的提示
Unrestricted
:安全警告
僅執行您信任的腳本。雖然來自 Internet 的腳本很有用,但此腳本可能會損害您的電腦。你想跑嗎
$$ D $$別跑 $$ R $$執行一次 $$ S $$暫停$$ ? $$幫助(預設為“D”):