运行 并通过 shell 脚本检查 sql 代理作业的结果
Running and checking the result of a sql agent job through a shell script
基本上我需要创建一个 shell 脚本来:
- 运行 SQL 远程服务器上的代理作业
- 等待运行
- 检查完成状态并能够保存/输出它以便进一步使用
我计划的方法是创建一个带有作业名称参数的存储过程,如下所示:
-- Start job
EXEC msdb.dbo.sp_start_job @job_name = @job_name
-- Wait for Job to finish
DECLARE @job_status INT
SELECT @job_status = current_execution_status FROM OPENROWSET('SQLNCLI', 'Server=<server>;','exec msdb.dbo.sp_help_job @job_name = @job_name ')
WHILE @job_status <> 4
BEGIN
WAITFOR DELAY '00:00:03'
SELECT @job_status = current_execution_status FROM OPENROWSET('SQLNCLI', 'Server=<server>;','exec msdb.dbo.sp_help_job @job_name = @job_name')
END
-- Get Result
SELECT TOP 1 @job_history_id = activity.job_history_id
FROM msdb.dbo.sysjobs jobs
INNER JOIN msdb.dbo.sysjobactivity activity ON activity.job_id = jobs.job_id
WHERE jobs.name = @job_name
ORDER BY activity.start_execution_date DESC
SELECT history.run_status
FROM msdb.dbo.sysjobhistory history
WHERE history.instance_id = @job_history_id
理想情况下,我可以通过这个 stored_proc 运行 每个 SQL 代理工作,所以我可以很容易地通过 sqlcmd
调用这个 stored_proc 和工作名称作为参数并将输出保存为作业的结果。
由于我对 SQL 服务器不是最有经验的,所以我来向大家寻求帮助。
- 我的存储过程是efficient/functional吗?任何人都可以启发我更好的方法吗?
- 是否应在 msdb 数据库上创建此存储过程?如果是,是否应将其保存为系统对象?
- 这是否会 post 迁移或任何管理问题(即迁移 SQL 版本/到不同服务器以保留此存储过程的特殊操作)?
在此先感谢您的支持。
对于寻找此问题答案的任何人,我找到了一个运行良好的存储过程:
CREATE PROCEDURE dbo.sp_sp_start_job_wait
(
@job_name SYSNAME,
@WaitTime DATETIME = '00:00:10', --check frequency
@JobCompletionStatus INT = null OUTPUT
)
AS
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET NOCOUNT ON
DECLARE @job_id UNIQUEIDENTIFIER
DECLARE @job_owner sysname
-- Create temp table with xp_sqlagent_enum_jobs structure
CREATE TABLE #xp_results (job_id UNIQUEIDENTIFIER NOT NULL,
last_run_date INT NOT NULL,
last_run_time INT NOT NULL,
next_run_date INT NOT NULL,
next_run_time INT NOT NULL,
next_run_schedule_id INT NOT NULL,
requested_to_run INT NOT NULL, -- BOOL
request_source INT NOT NULL,
request_source_id sysname COLLATE database_default NULL,
running INT NOT NULL, -- BOOL
current_step INT NOT NULL,
current_retry_attempt INT NOT NULL,
job_state INT NOT NULL)
SELECT @job_id = job_id FROM msdb.dbo.sysjobs
WHERE name = @job_name
SELECT @job_owner = SUSER_SNAME()
INSERT INTO #xp_results
EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id
-- Start the job if the job is not running
IF NOT EXISTS(SELECT TOP 1 * FROM #xp_results WHERE running = 1)
EXEC msdb.dbo.sp_start_job @job_name = @job_name
-- wait a couple of seconds to compute
WAITFOR DELAY '00:00:02'
DELETE FROM #xp_results
INSERT INTO #xp_results
EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id
WHILE EXISTS(SELECT TOP 1 * FROM #xp_results WHERE running = 1)
BEGIN
WAITFOR DELAY @WaitTime
DELETE FROM #xp_results
INSERT INTO #xp_results
EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id
END
SELECT top 1 @JobCompletionStatus = run_status
FROM msdb.dbo.sysjobhistory
WHERE job_id = @job_id
and step_id = 0
order by run_date desc, run_time desc
IF @JobCompletionStatus = 1
PRINT 'The job ran Successful'
ELSE IF @JobCompletionStatus = 3
PRINT 'The job is Cancelled'
ELSE
BEGIN
RAISERROR ('[ERROR]:%s job is either failed or not in good state. Please check',16, 1, @job_name) WITH LOG
END
RETURN @JobCompletionStatus
GO
基本上我需要创建一个 shell 脚本来:
- 运行 SQL 远程服务器上的代理作业
- 等待运行
- 检查完成状态并能够保存/输出它以便进一步使用
我计划的方法是创建一个带有作业名称参数的存储过程,如下所示:
-- Start job
EXEC msdb.dbo.sp_start_job @job_name = @job_name
-- Wait for Job to finish
DECLARE @job_status INT
SELECT @job_status = current_execution_status FROM OPENROWSET('SQLNCLI', 'Server=<server>;','exec msdb.dbo.sp_help_job @job_name = @job_name ')
WHILE @job_status <> 4
BEGIN
WAITFOR DELAY '00:00:03'
SELECT @job_status = current_execution_status FROM OPENROWSET('SQLNCLI', 'Server=<server>;','exec msdb.dbo.sp_help_job @job_name = @job_name')
END
-- Get Result
SELECT TOP 1 @job_history_id = activity.job_history_id
FROM msdb.dbo.sysjobs jobs
INNER JOIN msdb.dbo.sysjobactivity activity ON activity.job_id = jobs.job_id
WHERE jobs.name = @job_name
ORDER BY activity.start_execution_date DESC
SELECT history.run_status
FROM msdb.dbo.sysjobhistory history
WHERE history.instance_id = @job_history_id
理想情况下,我可以通过这个 stored_proc 运行 每个 SQL 代理工作,所以我可以很容易地通过 sqlcmd
调用这个 stored_proc 和工作名称作为参数并将输出保存为作业的结果。
由于我对 SQL 服务器不是最有经验的,所以我来向大家寻求帮助。
- 我的存储过程是efficient/functional吗?任何人都可以启发我更好的方法吗?
- 是否应在 msdb 数据库上创建此存储过程?如果是,是否应将其保存为系统对象?
- 这是否会 post 迁移或任何管理问题(即迁移 SQL 版本/到不同服务器以保留此存储过程的特殊操作)?
在此先感谢您的支持。
对于寻找此问题答案的任何人,我找到了一个运行良好的存储过程:
CREATE PROCEDURE dbo.sp_sp_start_job_wait
(
@job_name SYSNAME,
@WaitTime DATETIME = '00:00:10', --check frequency
@JobCompletionStatus INT = null OUTPUT
)
AS
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET NOCOUNT ON
DECLARE @job_id UNIQUEIDENTIFIER
DECLARE @job_owner sysname
-- Create temp table with xp_sqlagent_enum_jobs structure
CREATE TABLE #xp_results (job_id UNIQUEIDENTIFIER NOT NULL,
last_run_date INT NOT NULL,
last_run_time INT NOT NULL,
next_run_date INT NOT NULL,
next_run_time INT NOT NULL,
next_run_schedule_id INT NOT NULL,
requested_to_run INT NOT NULL, -- BOOL
request_source INT NOT NULL,
request_source_id sysname COLLATE database_default NULL,
running INT NOT NULL, -- BOOL
current_step INT NOT NULL,
current_retry_attempt INT NOT NULL,
job_state INT NOT NULL)
SELECT @job_id = job_id FROM msdb.dbo.sysjobs
WHERE name = @job_name
SELECT @job_owner = SUSER_SNAME()
INSERT INTO #xp_results
EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id
-- Start the job if the job is not running
IF NOT EXISTS(SELECT TOP 1 * FROM #xp_results WHERE running = 1)
EXEC msdb.dbo.sp_start_job @job_name = @job_name
-- wait a couple of seconds to compute
WAITFOR DELAY '00:00:02'
DELETE FROM #xp_results
INSERT INTO #xp_results
EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id
WHILE EXISTS(SELECT TOP 1 * FROM #xp_results WHERE running = 1)
BEGIN
WAITFOR DELAY @WaitTime
DELETE FROM #xp_results
INSERT INTO #xp_results
EXECUTE master.dbo.xp_sqlagent_enum_jobs 1, @job_owner, @job_id
END
SELECT top 1 @JobCompletionStatus = run_status
FROM msdb.dbo.sysjobhistory
WHERE job_id = @job_id
and step_id = 0
order by run_date desc, run_time desc
IF @JobCompletionStatus = 1
PRINT 'The job ran Successful'
ELSE IF @JobCompletionStatus = 3
PRINT 'The job is Cancelled'
ELSE
BEGIN
RAISERROR ('[ERROR]:%s job is either failed or not in good state. Please check',16, 1, @job_name) WITH LOG
END
RETURN @JobCompletionStatus
GO