描述
我們有一台數據庫服務器windows 2012 r2 上有安裝sql server 2012 和sql server 2016雙實例,后續又把sql 2016的服務全部停用,即只保留sql 2012 的服務在用。在例行檢查數據庫的job 運行情況時發現syspolicy_purge_history該自帶的job一直是失敗的,錯誤一直停留在step 3,
首先先了解一下該job的官方文檔說明,發現雖然跟實際在用的業務功能沒有什么關聯,但還是覺得有必要修復。
操作步驟
a.查看job的具體報錯提示
消息 已以用戶 XXXXXXXXX 的身份執行。 作業步驟在 PowerShell 腳本的行 1 中接收到錯誤。對應行為“import-module SQLPS -DisableNameChecking”。更正腳本並重新安排作業。PowerShell 返回的錯誤信息為“未能加載文件或程序集“file:///C:\Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\SQLPS\Microsoft.SqlServer.Management.PSSnapins.dll”或它的某一個依賴項。生成此程序集的運行時比當前加載的運行時新,無法加載此程序集。 ”. 進程退出代碼 -1。. 該步驟失敗。
查看該step 3 代碼如下:
if ('$(ESCAPE_SQUOTE(INST))' -eq 'MSSQLSERVER') {$a = '\DEFAULT'} ELSE {$a = ''}; (Get-Item SQLSERVER:\SQLPolicy\$(ESCAPE_NONE(SRVR))$a).EraseSystemHealthPhantomRecords()
其中對
ESCAPE_比較困惑,感覺不像是powershell ,查看幫助才知道是sql server agent 的tonkens.
b.在powershell 運行Import-Moduls 語句
還是一樣無法加載該文件,那么升級到powhershell 5 能否解決該問題,因涉及到安裝可能會重啟服務器不確定因素,慎重起見該方案非首先選。竟然是無法加載該文件,那么直接使用sql 2012 對應的文件是不是就可以了,順着這個思路,那么問題就變成了如何讓step 3這步執行的默認去sql 2012的路徑找。
c.修改環境變量

默認的內容
%ProgramFiles%\WindowsPowerShell\Modules;%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules;C:\Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\
修改為
%ProgramFiles%\WindowsPowerShell\Modules;%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\;C:\Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\
即把sql 2016和sql 2012 的路徑調換一下。
d.重新執行job驗證
后記
后續遇到類似的syspolicy_purge_history的step3執行失敗的案例A如下:
日期 2019/6/15 8:01:25 日志 作業歷史記錄 (syspolicy_purge_history) 步驟 ID 3 服務器 D********* 作業名稱 syspolicy_purge_history 步驟名稱 Erase Phantom System Health Records. 持續時間 00:00:00 SQL 嚴重性 0 SQL 消息 ID 0 已通過電子郵件通知的操作員 已通過網絡發送通知的操作員 已通過尋呼通知的操作員 重試次數 0 消息 無法開始執行步驟 3 (原因: PowerShell 子系統加載失敗 [有關詳細信息,請參閱 SQLAGENT.OUT 文件];該作業已掛起). 該步驟失敗。
對應的SQLAGENT.OUT 文件部分內容如下:
2019-06-14 16:04:12 - ! [125] 無法加載子系統“PowerShell”(原因: 系統找不到指定的路徑。) 2019-06-14 16:04:12 - ? [129] SQLSERVERAGENT 在 Windows NT 服務控制下啟動 2019-06-14 16:04:12 - + [475] 沒有為代理通知啟用數據庫郵件。 2019-06-14 16:04:12 - + [396] 尚未定義空閑 CPU 條件 - OnIdle 作業計划將不起任何作用 2019-06-15 08:01:25 - ! [LOG] 未能加載 PowerShell 子系統,所以不能運行作業“syspolicy_purge_history”(0x8CEE075FE296DF4DA6B50C671B32C757)的步驟 3。該作業已掛起。 2019-06-16 22:13:31 - + [000] 運行作業 syspolicy_purge_history 的請求(來自 計划 8 (syspolicy_purge_history_schedule))被拒絕,因為該作業已掛起 2019-06-17 07:40:44 - + [000] 運行作業 syspolicy_purge_history 的請求(來自 計划 8 (syspolicy_purge_history_schedule))被拒絕,因為該作業已掛起 2019-06-18 07:51:42 - + [000] 運行作業 syspolicy_purge_history 的請求(來自 計划 8 (syspolicy_purge_history_schedule))被拒絕,因為該作業已掛起 2019-06-19 07:41:52 - + [000] 運行作業 syspolicy_purge_history 的請求(來自 計划 8 (syspolicy_purge_history_schedule))被拒絕,因為該作業已掛起 2019-06-20 07:47:37 - + [000] 運行作業 syspolicy_purge_history 的請求(來自 計划 8 (syspolicy_purge_history_schedule))被拒絕,因為該作業已掛起
解決步驟
第一步:查詢文件路徑
--step 1 SELECT * FROM msdb.dbo.syssubsystems WHERE start_entry_point ='PowerShellStart'



第三步:查詢sqlps.exe文件路徑,如沒有需其他服務器上拷貝同版本的文件。


第四步:修改路徑
Use msdb go sp_configure 'allow updates', 1 RECONFIGURE WITH OVERRIDE
第六步: 重新執行syspolicy_purge_history
發現還是掛起,當前使用的sql server 2016 ,重新查詢路徑發現又恢復成原始的路徑,竟然走不通,那把文件直接拷貝到對應的路徑下試試。重新按上述步驟走一遍;
發現還是失敗,直接在路徑中打開這個SQLPS.exe文件,發現如下錯誤


import-module : 未能加載指定的模塊“SQLPS”,因為在任何模塊目錄中都沒有找到有效模塊文件。 所在位置 行:1 字符: 1 + import-module SQLPS + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ResourceUnavailable: (SQLPS:String) [Import-Module], FileNotFoundException + FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
對比其他服務器發現Tools文件夾下缺失PowerShell文件夾,從其他同版本的服務器拷貝一個過來,如下:

重復上述步驟再執行job


問題終於解決;
還有可能因其他原因
出現上述的場景也可以參考這鏈接;
案例B
日期 2019/6/19 17:43:07 日志 作業歷史記錄 (syspolicy_purge_history) 步驟 ID 3 服務器 S***** 作業名稱 syspolicy_purge_history 步驟名稱 Erase Phantom System Health Records. 持續時間 00:00:30 SQL 嚴重性 0 SQL 消息 ID 0 已通過電子郵件通知的操作員 已通過網絡發送通知的操作員 已通過尋呼通知的操作員 重試次數 0 消息 已以用戶 HDJT\sprsql 的身份執行。 作業步驟在 PowerShell 腳本的行 1 中接收到錯誤。對應行為“set-executionpolicy RemoteSigned -scope process -Force”。更正腳本並重新安排作業。PowerShell 返回的錯誤信息為“安全性錯誤。 ”. 進程退出代碼 -1。. 該步驟失敗。
這個是sql server 2012版本;
官方的解決方法如下
SQL Server 2008年或 SQL Server 2008 R2 在無法啟動 SQL PowerShell RemoteSigned策略。在 SQL Server 2008年中,因此,作業不會失敗。作為一種安全措施,SQL Server 2012年啟動 SQL PowerShell RemoteSigned策略中。這將導致作業失敗,前面的問題發生。
不受限制的明確建議不要從安全角度因為這意味着沒有限制。PowerShell 腳本運行成功時MachinePolicy設置為在域控制器中的RemoteSigned從 SQL 2012 年啟動時,這就是原因。
要解決此問題,請使用下列方法之一︰
不受限制的明確建議不要從安全角度因為這意味着沒有限制。PowerShell 腳本運行成功時MachinePolicy設置為在域控制器中的RemoteSigned從 SQL 2012 年啟動時,這就是原因。
要解決此問題,請使用下列方法之一︰
- 不要設置域控制器 GPO 的計算機策略。如果未定義,這意味着下一個級別策略 (示例中, UserPolicy,然后流程,然后為CurrentUser,和上一次LocalMachine) 將優先。
- 在 Active Directory 用戶和計算機中創建新組織單位 (OU) 並將鏈接組策略的 OU。然后啟用 RemoteSigned 策略。若要執行此操作,請執行以下步驟:
- 轉到Active Directory 用戶和計算機。
- 用鼠標右鍵單擊您的域->新建->組織單位創建新的組織單位。
- 在運行,鍵入gpmc.msc ,然后用鼠標右鍵單擊組策略對象->新建以創建新的 GPO。
- 用鼠標右鍵單擊新創建的 GPO->編輯。它會打開一個新窗口。
- 轉到計算機配置->策略->管理模板-> Windows 組件-> Windows PowerShell -> 雙擊打開腳本執行
- 設置為允許本地腳本和遠程簽名的腳本的執行策略
- 單擊應用,然后單擊確定。
- 轉到Active Directory 用戶和計算機,然后單擊計算機。在域中找到計算機的列表。右鍵單擊您希望移動在新創建的組織單位中的計算機。以這種方式,可以將單個或一組計算機移動到一個組織單位。
- 轉到組策略管理用鼠標右鍵單擊新創建的組織單位、 單擊鏈接現有的 GPO、 選擇新創建的 GPO,然后單擊確定。
- 通過運行此命令繼續更新域控制器和客戶端計算機上的策略。
gpupdate /force - 驗證計算機策略的組織單位和客戶端組件,它應該RemoteSigned。