Вопрос 1)
Планируем отключить XP CMDSHELL в SQL. Есть ли альтернатива методу, который я использую ниже:
Вопрос 2)
Ниже SP
1. Создает новое SQL задание каждый раз 2. Запускает CMD команда, переданная ему из параметра 3 SP. Наконец, SP возвращает результат
USE [Test]
GO
/****** Object: StoredProcedure [dbo].[CMDSHELL_ALTERNATIVE] Script Date: 5/8/2020 5:44:39 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CMDSHELL_ALTERNATIVE]
@Command varchar(200),
@InvokedBySP varchar(100) = 'AdhocCalling'
AS
BEGIN
DECLARE @OutputFileName varchar(max)
DECLARE @OutputFilePath varchar(max)
DECLARE @JobOutcome int = 5
DECLARE @JobMessage varchar(max)
DECLARE @TodayDate DATE = GETDATE()
DECLARE @JobExecutionTime DATETIME
DECLARE @RandomeNumber BIGINT = CAST(RAND() * 1000000 AS BIGINT)
DECLARE @JobName varchar(100) = 'CMDSHELL_JOB_'+ CAST(@TodayDate AS VARCHAR)+'_'+CAST(@RandomeNumber AS VARCHAR)
SET @OutputFilePath ='C:\Users\OutputFiles\'
SET @OutputFileName = @JobName+'.txt'
DECLARE @FullOutputFilePathName varchar(max) = @OutputFilePath+@OutputFileName
DECLARE @jobId BINARY(16)
EXEC msdb.dbo.sp_add_job @job_name=@JobName,
@enabled=1,
@notify_level_eventlog=0,
@notify_level_email=2,
@notify_level_page=2,
@delete_level=0,
@category_name=N'[Uncategorized (Local)]',
@owner_login_name=N'sa', @job_id = @jobId OUTPUT
EXEC msdb.dbo.sp_add_jobserver @job_name=@JobName, @server_name = N'(local)'
EXEC msdb.dbo.sp_add_jobstep @job_name=@JobName, @step_name=N'step-1',
@step_id=1,
@cmdexec_success_code=0,
@on_success_action=1,
@on_fail_action=2,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0, @subsystem=N'CmdExec',
@command=N'',
@database_name=N'master',
@output_file_name=N'',
@flags=0
EXEC msdb.dbo.sp_update_job @job_name=@JobName,
@enabled=1,
@start_step_id=1,
@notify_level_eventlog=0,
@notify_level_email=2,
@notify_level_page=2,
@delete_level=0,
@description=N'',
@category_name=N'[Uncategorized (Local)]',
@owner_login_name=N'sa',
@notify_email_operator_name=N'',
@notify_page_operator_name=N''
EXEC msdb.dbo.sp_update_jobstep
@job_name=@JobName,
@step_id=1 ,
@command=@Command,
@output_file_name=@FullOutputFilePathName
EXEC msdb.dbo.sp_start_job @JobName
SELECT distinct @JobOutcome = SJH.run_status
FROM msdb..sysjobhistory SJH, msdb..sysjobs SJ
WHERE SJH.job_id = SJ.job_id and SJ.Name = @JobName
WHILE (@JobOutcome != 3 AND @JobOutcome > 1)
BEGIN
print 'In a delay loop'
WAITFOR DELAY '00:00:02';
SELECT distinct @JobOutcome = SJH.run_status
FROM msdb..sysjobhistory SJH, msdb..sysjobs SJ
WHERE SJH.job_id = SJ.job_id and SJ.Name = @JobName
END
SET @JobExecutionTime = GETDATE()
SELECT @JobMessage = message FROM msdb..sysjobhistory SJH, msdb..sysjobs SJ
WHERE SJH.job_id = SJ.job_id and SJ.Name = @JobName
AND step_id = 1
IF @JobOutcome = 1
BEGIN
print 'Job successfull'
Declare @BulkInsertCommand varchar(max)
CREATE TABLE #temp (results NVARCHAR(755))
SET @BulkInsertCommand =
'BULK INSERT #temp
FROM ''' + @FullOutputFilePathName +'''
WITH
(
ROWTERMINATOR = ''\n'',
DataFileType=''widechar''
)'
EXEC (@BulkInsertCommand)
Select results from #temp
execute Test.dbo.CLR_CMDSHELL_LOGGING @JobName,@InvokedBySP,@Command,@JobExecutionTime,'Job Successfull',@JobMessage
END
ELSE
BEGIN
print 'Dynamic Job failed'
execute Test.dbo.CLR_CMDSHELL_LOGGING @JobName,@InvokedBySP,@Command,@JobExecutionTime,'Job Failed',@JobMessage
END
IF EXISTS (SELECT job_id FROM msdb.dbo.sysjobs_view WHERE name = @JobName)
EXEC msdb.dbo.sp_delete_job @job_name=@JobName
END
Теперь я запускаю выше SP, используя следующий код -
DECLARE @cmd VARCHAR(100)
SET @cmd = 'DIR /B C:\Users\Test'
--DECLARE @dirTable TABLE (oPut VARCHAR(max))
--insert @dirTable
EXEC [dbo].CMDSHELL_ALTERNATIVE @cmd
--select * from @dirTable
Результат без вставки
введите описание изображения здесь
Проблема
Код выше без вставки работает нормально, быстро возвращает результат. Но когда оператор Insert раскомментирован, SP работает вечно.
введите здесь описание изображения enter code here
Я не могу понять, где именно блокируется. Любая альтернатива / исправление выше?