I recently wanted to put output files on all job steps running on all my sql servers. I wanted the output filenames to be unique and I found that you can use tokens to achieve this. However it does not let you use the job name, as I wanted an easy to read filename (not having to look up a guid everytime I am searching for an output file) I came up with the following SQL that will add an output file to every job step in the sysjobsteps tables.
I used a couple of references to get to this (see end of article), and the script runs daily to ensure added jobs also get the outputfile treatment.
The output filename generated by this will be
SQLAGENT_JOB_<jobname>_StepID-<stepID>_<date>_<time>.txt
the actual outputfile string that will appear in the step output file will look something like this (the $() are the SQL tokens that will be replaced with values when the output file is created by SQL Server)
<filelocation>\SQLAGENT_JOB_Daily_Backup_StepID-$(ESCAPE_SQUOTE(STEPID))_$(ESCAPE_SQUOTE(STRTDT))_$(ESCAPE_SQUOTE(STRTTM)).txt.
- edit: After running this for a day, it became apparent that I was going to have a mass of files for jobs that run multiple times a day. To alleviate this I have now change the output file to just include the date and not time. Just means I have 1 file for each job step for each day. Please note the difference between the above and the code below. The main code example has also been updated.
- <filelocation>\SQLAGENT_JOB_Daily_Backup_<jobname>_StepID-$(ESCAPE_SQUOTE(STEPID))_$(ESCAPE_SQUOTE(STRTDT)).txt.
- edit: Ok further edit, I did not notice that the token $(ESCAPE_SQUOTE(STEPID)) was actually inserting only ID value 1 on all steps. I am not sure of the reason as the other tokens are working fine. Any way I redesigned the query to use the <filelocation>\SQLAGENT_JOB_Daily_Backup_<jobname>_StepID-<stepID>_$(ESCAPE_SQUOTE(STRTDT)).txt.
I include both scripts. I have an inkling that this is something to do with the fact the job started at step 1 and thats the what the stepid holds (the starting step), but thats just a feeling.
Script 1 – with stepID token
DECLARE @output_file_name_prefix varchar (512)DECLARE @output_file_name_postfix varchar (512)DECLARE @job_id varchar(512)DECLARE @step_id varchar(10)DECLARE @job_name varchar(255)DECLARE JobList CURSOR FORSELECT job_id, step_id FROM msdb.dbo.sysjobstepsOPEN JobListFETCH NEXT FROM JobList INTO @job_id, @step_idSET @output_file_name_prefix = '<filelocation>\SQLAGENT_JOB_'SET @output_file_name_postfix = '_StepID-$(ESCAPE_SQUOTE(STEPID)_$(ESCAPE_SQUOTE(STRTDT)).txt'WHILE @@FETCH_STATUS = 0BEGINSELECT @job_name = name FROM msdb.dbo.sysjobs WHERE job_id = @job_idSET @output_file_name = @output_file_name_prefix + REPLACE(@job_name, ' ', '_') + @output_file_name_postfixEXECUTE msdb.dbo.sp_update_jobstep@job_id = @job_id,@step_id = @step_id,@output_file_name = @output_file_name,@flags = 2 -- append to output file
FETCH NEXT FROM JobList INTO @job_id, @step_idENDCLOSE JobListDEALLOCATE JobList
Script 2 – with stepID token replaced
DECLARE @output_file_name varchar (2048)DECLARE @output_file_name varchar (2048)DECLARE @output_file_name_prefix varchar (512)DECLARE @output_file_name_midfix varchar (512)DECLARE @output_file_name_postfix varchar (512)DECLARE @job_id varchar(512)DECLARE @step_id varchar(10)DECLARE @job_name varchar(255)DECLARE JobList CURSOR FORSELECT job_id, step_id FROM msdb.dbo.sysjobstepsOPEN JobListFETCH NEXT FROM JobList INTO @job_id, @step_idSET @output_file_name_prefix = '<file location>\SQLAGENT_JOB_'SET @output_file_name_midfix = '_StepID-'SET @output_file_name_postfix = '_$(ESCAPE_SQUOTE(STRTDT)).txt'WHILE @@FETCH_STATUS = 0BEGINSELECT @job_name = name FROM msdb.dbo.sysjobs WHERE job_id = @job_idSET @output_file_name = @output_file_name_prefix + REPLACE(@job_name, ' ', '_') + @output_file_name_midfix + @step_id + @output_file_name_postfixEXECUTE msdb.dbo.sp_update_jobstep@job_id = @job_id,@step_id = @step_id,@output_file_name = @output_file_name,@flags = 2 -- append to output file
FETCH NEXT FROM JobList INTO @job_id, @step_idENDCLOSE JobListDEALLOCATE JobList
For information the jobs and jobssteps are held in the MSDB system database in SQL Server in the msdb.dbo.sysjobs and msdb.dbo.sysjobsteps tables.References
As a quick aside to this, in the job I scheduled to run the above script I was included a second step to clear up the output files I created. The command below will delete files over 30 days old. Note: forfiles command is only native on Windows 2003+ server. The SQL job step runs a type Operating system (CmdExec).
forfiles /P "<file location>" /D -30 /C "cmd /c DEL /F /Q @path"
http://ask.sqlservercentral.com/questions/1148/saving-jobs-output-to-a-text-file
http://msdn.microsoft.com/en-us/library/ms175575.aspx
http://support.microsoft.com/kb/111401