我正在尝试构建 SAS 代码来查看过去的日志、重新运行失败的报告并通知重新运行状态。我正在使用&syscc。宏来检查我的重新运行尝试中是否存在错误,并在每次尝试之间重置它。但是,我在宏 %do 循环中使用 syscc 时遇到了问题,因为 syscc 没有显示正确的错误代码。 IE。它没有显示第一个循环的任何错误,尽管它应该显示,然后它无法重置回 0。(共享下面的代码段)。是否有使用 syscc 的替代方法或其他编写宏的方法?
%macro rerunner();
%do i=1 %to &numrecs;
%put &i;
/*selecting a log and code*/
proc sql;
select cname into : selected_code separated by ','
from code_logs
where rown=&i;
quit;
proc sql;
select lname into : selected_log separated by ','
from code_logs
where rown=&i;
quit;
/*counting errors*/
data _null_;
infile "&loglocation./&selected_log." end=last;
input;
if _infile_ =: 'ERROR' then error_count+1;
if last and error_count >=1 then CALL EXECUTE('%rerun(&selected_log. , &selected_code.)') ;
if last and error_count < 1 then CALL EXECUTE('%no_rerun(&selected_log.)') ;
run;
%end;
%mend;
%macro rerun(log,code);
%let syscc = 0;
%include "&codelocation./&code." ;
%if &syscc. <= 6 %then %do;
%success(&log.);
%end;
%else %do;
%failure(&log.)
%end;
%mend;
...
%rerunner();
这里有一个时间问题。您的宏
%rerun
正在使用在发生任何事情之前定义的 &syscc!
思考这个问题的方法是将其视为有 2 个通道。首先是“宏观”通道,然后是“SAS”通道。
所以 %rerun 像这样工作。
起始代码:
%macro rerun(log,code);
%let syscc = 0;
%include "&codelocation./&code." ;
%if &syscc. <= 6 %then %do;
%success(&log.);
%end;
%else %do;
%failure(&log.)
%end;
%mend;
宏展开步骤:
%let syscc=0;
-- syscc=0
%include "&codelocation./&code.";
-- 将该位置的代码包含到 SAS 代码中(但不运行它)
%if &syscc <= 6 %then %do;
%success(&log.);
%end;
-- syscc=0,所以小于六,所以做这部分 -- 将宏成功展开到 SAS 代码中并将其包含在此处
%else %do;
%end;
——这没有任何作用,因为 if 是 true
现在,
%rerun
宏进入 SAS 代码步骤,并实际执行操作。除了...代码是否设置错误并不重要,因为不再在任何地方检查 syscc - 它已经通过 syscc=0
路径。
如果你想做这样的事情,你需要有一种方法在宏执行期间交互式地查找syscc的值。这是可能的,但这不是最好的设计。
这里更好的设计是在宏(或其他)执行结束时将 &syscc 的值存储到数据集中,并检查 that,可能会从中调用重新运行。
data syscc_status;
input prog $ timestamp :datetime17. syscc;
datalines;
prog1 01JAN2024:01:01:01 3
prog2 01JAN2024:01:01:02 8
prog3 01JAN2024:01:01:03 6
;;;;
run;
类似这样的事情。然后你的程序运行时可以像这样在包装器中:
%macro runprogram(program=,log=);
%let syscc=0;
proc printto log="&log";
run;
%include "&program";
proc printto;
run;
data syscc_append;
prog="&program";
timestamp = now();
syscc=&syscc;
run;
proc append base=syscc_status data=syscc_append;
run;
%mend runprogram;
现在你可以做这样的事情:
proc sql;
select cats('%rerun(program=',prog,')') into :proglist separated by ' '
from syscc_status
where timestamp gt dhms(today(),0,0,0)
;
quit;
&proglist;
并且您的
%rerun
宏只是调用 runprogram 宏(它可能只是直接调用 runprogram 宏,除非您想做其他事情)。显然,如果不简单,您可能还需要发送日志名称。