有效停止大型SAS程序

有效停止大型SAS程序,sas,sas-macro,Sas,Sas Macro,我有一个非常大的SAS程序,大约有50个子程序,每个程序都有许多步骤。目前,无论是否存在错误,它都将运行到完成。但是,当发生错误时,我要求它停止并退出 请注意(我认为)SYSERR宏不适合此任务,因为我需要在每个单独步骤结束时(例如,在每个数据或过程步骤之后)检查SYSERR,因为SYSERR在每个步骤边界之后重置;这将是一项非常耗时且容易出错的任务,因为在我的50个子程序中,每个程序都有数千个不同的步骤边界 我设想的解决方案包括在每个(50个)子程序运行后立即检查它们生成的日志文件,然后在日志

我有一个非常大的SAS程序,大约有50个子程序,每个程序都有许多步骤。目前,无论是否存在错误,它都将运行到完成。但是,当发生错误时,我要求它停止并退出

请注意(我认为)SYSERR宏不适合此任务,因为我需要在每个单独步骤结束时(例如,在每个数据或过程步骤之后)检查SYSERR,因为SYSERR在每个步骤边界之后重置;这将是一项非常耗时且容易出错的任务,因为在我的50个子程序中,每个程序都有数千个不同的步骤边界

我设想的解决方案包括在每个(50个)子程序运行后立即检查它们生成的日志文件,然后在日志文件中出现错误时停止(或者在没有错误时继续执行下一个子程序)。然而,我无法想象如何做到这一点。
非常感谢。

我认为,您检查日志的解决方案是好的。 因为您可以过滤“警告”、“错误”或“错误:”等登录词。 如果行中包含这些错误关键字,则可以将过去的日志复制到excel并进行筛选

但是,我在SAS中有一个解决方案

1) 使用proc printto创建日志 2) 关闭“打印到重定向”过程 3) 用SAS实现日志的自动分析

以下是宏函数的代码:

/**
*
* @dev Function to create a log for a program
* @param job The name of the job to be logged
*
*/

%macro runjob(job /*Enter the name of the job to log Ex: myjob*/);
    option fullstimer;

    %let runjob=%sysfunc(compress(&job._%sysfunc(datetime(),b8601dt)));
    data _null_;
        call symputx("runjob","&runjob.",'G');
    run;

    filename logfile "C:\LOG\&runjob..log";

    proc printto log=logfile new;
    run;

%mend runjob; /* %runjob(myjob); */


/**
*
* @dev Funtion to check if a table is empty
* @param inset The name of dataset to be checked
*
*/

%macro checkTableIfEmpty(inset /* Write the name of your dataset (ex: checklog) */);
    %let dsid = %sysfunc (open(&inset));


    %if &dsid ge 0 %then
        %let dsid = 1;
    %let anyobs = %sysfunc (attrn(&dsid,ANY));
    %let dsid = %sysfunc (close(&dsid));

    %put anyobs=&anyobs;

    %if &anyobs = 1 %then
        %do;

            data _null_;
                call symputx('checkTableIfEmpty',0,'G');
            run;

        %end;
    %else
        %do;

            data _null_;
                call symputx('checkTableIfEmpty',1,'G');
            run;

        %end;
%mend checkTableIfEmpty; /* %checkTableIfEmpty(checklog); */


/**
*
* @dev Function to filter a log file from SAS with words like "warning" and "error"
* @param inp The pathname of the log to be checked
*
*/

%macro checkLog(inp /* Write the pathname of the log to be checked (ex: myjob_20170818T161545.log) */);

    data empty_marker;
        length MSG $200;
        MSG='No error(s)/warning(s).';
    run;

    DATA CHECKLOG;
        LENGTH ROWS $200;
        LABEL ROWS = 'Messages from LOG';
        INFILE "&inp" TRUNCOVER;
        INPUT ROWS &;
        LINE = _N_;

        IF SUBSTR(ROWS,1,5)='ERROR' OR SUBSTR(ROWS,1,7)='WARNING' THEN
            OUTPUT;
    RUN;

    %checkTableIfEmpty(checklog);

    ODS HTML BODY="C:\LOG\log.html" STYLE=sasweb;
    TITLE1 "Messages from LOG";

    %if &checkTableIfEmpty = 0 %then
        %do;
            proc sql;
                select distinct(rows) from checklog;
            run;

        %end;
    %else
        %do;

            proc print data=empty_marker;
            run;

        %end;

    ODS HTML CLOSE;
%mend checkLog; /*  %checkLog(c:\LOG\myjob_20170818T161545.log);  */
然后,您可以在这样的程序中使用这些函数

%let jobname=myjob;
/* START */
%runjob(&jobname);

...

/*END*/
proc printto;
run;

%checkLog(C:\LOG\&runjob..log);
您将在C:\LOG\LOG.html中获得一个html文件

Messages from LOG
ERROR: Ambiguous reference, column DateSent is in more than one table. 
ERROR: Ambiguous reference, column Operation_date is in more than one table. 
ERROR: Expression using equals (=) has components that are of different data types. 
ERROR: Expression using less than or equal (<=) has components that are of different data types. 
来自日志的消息
错误:引用不明确,DateSent列位于多个表中。
错误:引用不明确,列操作日期在多个表中。
错误:使用equals(=)的表达式包含不同数据类型的组件。

错误:使用小于或等于(的表达式来检查日志,我认为是好的解决方案。 因为您可以过滤“警告”、“错误”或“错误:”等登录词。 如果行中包含这些错误关键字,则可以将过去的日志复制到excel并进行筛选

但是,我在SAS中有一个解决方案

1) 使用proc printto创建日志 2) 关闭“打印到重定向”过程 3) 用SAS实现日志的自动分析

以下是宏函数的代码:

/**
*
* @dev Function to create a log for a program
* @param job The name of the job to be logged
*
*/

%macro runjob(job /*Enter the name of the job to log Ex: myjob*/);
    option fullstimer;

    %let runjob=%sysfunc(compress(&job._%sysfunc(datetime(),b8601dt)));
    data _null_;
        call symputx("runjob","&runjob.",'G');
    run;

    filename logfile "C:\LOG\&runjob..log";

    proc printto log=logfile new;
    run;

%mend runjob; /* %runjob(myjob); */


/**
*
* @dev Funtion to check if a table is empty
* @param inset The name of dataset to be checked
*
*/

%macro checkTableIfEmpty(inset /* Write the name of your dataset (ex: checklog) */);
    %let dsid = %sysfunc (open(&inset));


    %if &dsid ge 0 %then
        %let dsid = 1;
    %let anyobs = %sysfunc (attrn(&dsid,ANY));
    %let dsid = %sysfunc (close(&dsid));

    %put anyobs=&anyobs;

    %if &anyobs = 1 %then
        %do;

            data _null_;
                call symputx('checkTableIfEmpty',0,'G');
            run;

        %end;
    %else
        %do;

            data _null_;
                call symputx('checkTableIfEmpty',1,'G');
            run;

        %end;
%mend checkTableIfEmpty; /* %checkTableIfEmpty(checklog); */


/**
*
* @dev Function to filter a log file from SAS with words like "warning" and "error"
* @param inp The pathname of the log to be checked
*
*/

%macro checkLog(inp /* Write the pathname of the log to be checked (ex: myjob_20170818T161545.log) */);

    data empty_marker;
        length MSG $200;
        MSG='No error(s)/warning(s).';
    run;

    DATA CHECKLOG;
        LENGTH ROWS $200;
        LABEL ROWS = 'Messages from LOG';
        INFILE "&inp" TRUNCOVER;
        INPUT ROWS &;
        LINE = _N_;

        IF SUBSTR(ROWS,1,5)='ERROR' OR SUBSTR(ROWS,1,7)='WARNING' THEN
            OUTPUT;
    RUN;

    %checkTableIfEmpty(checklog);

    ODS HTML BODY="C:\LOG\log.html" STYLE=sasweb;
    TITLE1 "Messages from LOG";

    %if &checkTableIfEmpty = 0 %then
        %do;
            proc sql;
                select distinct(rows) from checklog;
            run;

        %end;
    %else
        %do;

            proc print data=empty_marker;
            run;

        %end;

    ODS HTML CLOSE;
%mend checkLog; /*  %checkLog(c:\LOG\myjob_20170818T161545.log);  */
然后,您可以在这样的程序中使用这些函数

%let jobname=myjob;
/* START */
%runjob(&jobname);

...

/*END*/
proc printto;
run;

%checkLog(C:\LOG\&runjob..log);
您将在C:\LOG\LOG.html中获得一个html文件

Messages from LOG
ERROR: Ambiguous reference, column DateSent is in more than one table. 
ERROR: Ambiguous reference, column Operation_date is in more than one table. 
ERROR: Expression using equals (=) has components that are of different data types. 
ERROR: Expression using less than or equal (<=) has components that are of different data types. 
来自日志的消息
错误:引用不明确,DateSent列位于多个表中。
错误:引用不明确,列操作日期在多个表中。
错误:使用equals(=)的表达式包含不同数据类型的组件。

错误:表达式使用小于或等于(您有SAS/Connect许可证吗?也许您可以将每个子程序生成为任务或rsubmit块?我有SAS许可证,所以可以尝试(我对SAS比较陌生,因此需要研究此方法)。可能的副本您是否有SAS/Connect许可证?也许您可以将每个子程序生成为任务或rsubmit块?我有SAS许可证,因此可以尝试(我对SAS比较陌生,因此需要研究此方法)。非常感谢你的回答!我已经实现了你的方法!非常感谢你的回答!我已经实现了你的方法!