☰
SAP后台作业SM36/37全解析:定时任务、变式与作业链实战
2026/9/28 7:07:53 网站建设 项目流程

做SAP这块的,几乎每天都会有人问:"那种每天凌晨自动跑、到点自动出报表的作业,到底在哪设置?"如果你在ERP项目里待过,很快会得到一个标准答案:SM36。SM36是SAP里创建后台作业的事务代码,配合SM37监控作业运行情况,基本就是传统ECC和S/4HANA里做批量自动化的标准入口。

很多刚接触SAP的人,第一反应是"SM36不就是新建一个作业,填个时间就行了?"真到落地的时候才会发现,变式怎么挂在程序上、周期条件怎么选才不出错、权限对象缺了为什么连保存都保存不了、作业明明显示Finished为什么数据没更新……这些坑一个比一个隐蔽。

这篇我会按真实的操作顺序来讲:先搞明白后台作业的调度逻辑,再讲建作业之前要备好的几个东西,然后是SM36的完整设置步骤,接着是作业不跑或跑挂了怎么排查,最后讲作业链、事件触发和用BAPI批量建作业这些进阶玩法。适合刚转SAP运维、刚接手FICO或MM模块月结任务、以及做SAP项目的乙方顾问们。

1. 后台作业的调度原理:弄懂“作业、步骤、开始条件”再动手

1.1 SM36到底在管什么:一个作业的三件套

很多人打开SM36,看到一堆输入框和按钮就发懵。其实你不用理解它的全部界面,只要抓住一个核心概念:一个后台作业,本质上就是"三件套"的集合。

第一件是作业本身(Job)。在SAP里,作业不是一个程序文件,而是一个"任务对象"。你可以把它理解成一个闹钟条目:它有自己的名字,有自己的优先级,有自己的归属用户,还有一个可选的执行主机。SM36创建作业时填的作业名、作业类、目标服务器,都是在定义这个"任务对象"的属性。

第二件是作业步骤(Step)。作业步骤才是真正干活的东西。最常见的一步是"ABAP程序调用",也就是指定系统里的某个报表或某个批量程序,再配合一个变式(Variant)来提供运行参数。除了程序,步骤也可以是外部命令、外部程序等,但日常90%以上用的都是ABAP程序。

第三件是开始条件(Start Condition)。在SM36里保存作业的时候,系统会强制你定义作业什么时候开始跑。可以立即执行,可以指定某年某月某日某时执行,也可以按照日、周、月、自定义周期循环执行。

这三件套的关系,我用一个生活化的例子说明:作业就像你买了一个插电式电饭煲,步骤就是放进米和水,开始条件就是"每天下午五点半开始煮饭"。米和水不对,饭煮出来是夹生的;时间设错了,饭煮出来没人吃。

搞懂这三件套之后,SM36整个界面的结构就清晰了:上面是作业属性,中间是步骤清单,保存时再设定开始条件。不要再被那一堆按钮带偏了。

1.2 从SM36到SM37:创建、释放、运行是一条完整链路

有些人在SM36里把作业建好,以为就万事大吉了,第二天去看发现作业压根没跑。出现这种情况,十有八九是对后台作业的"生命周期"理解不够。

一个作业的完整生命周期是这样的:在SM36里创建并保存时,作业状态是"已计划(Scheduled)",仅仅表示有这么一个条目存在。之后系统后台的调度器(Job Scheduler)会把符合条件的作业"释放(Released)",也就是让它进入等待执行的状态。释放之后,作业才会在真正的后台工作进程里抢时间片执行,进入"就绪(Ready)"和"运行中(Running)"状态,跑完才是"已完成(Finished)",跑挂就是"取消(Canceled)"。

这个过程,SM36本身是看不了的。SM36只管"定义",SM37才负责"监控"。运维人员的标准动作是:SM36建作业,SM37盯作业。如果作业一直停在已计划没被释放,先去看看调度器有没有在正常干活,或者是不是有人在RZ04里把目标服务器禁止了;如果作业已经是"已释放"但迟迟不进入就绪,多半是后台进程不够用了。

曾经有个客户,晚上八点有一批报表作业,天天晚上都跑,突然有一天全部卡住不动了。我在SM37里一看,状态全部是Ready,系统里全是正在跑的超长批处理,后台进程被塞满了。原因是有个开发同事临时放了个大报表在跑,把所有后台进程占住了。这种问题靠改作业根本没用,得去管进程和资源。

把这条生命周期链路刻在脑子里,会对后面所有排查有巨大帮助。状态不同,解决方案完全不同。

2. 动手前的准备工作:变式、权限和作业类,少了哪个都会翻车

2.1 变式:把选择屏幕的参数固化下来,否则作业就是空壳

变式(Variant)是SAP后台作业里最重要的概念之一,也是最容易忽略的一环。一个ABAP程序,通常在界面上会有一堆选择字段:公司代码、工厂、日期范围、物料类型等。你要让它批处理运行,就必须把这一堆字段的值提前保存好,程序运行的时候才能知道按什么参数去取数、去执行。

在SM36的作业步骤里,每个程序都可以挂一个变式。变式怎么来?打开这个程序的前台界面(SE38或SE43,多按一下F8执行),把需要的参数填好,然后在菜单栏里点保存变式,输入变式名,再点保存。就这么简单。变式本质上就是"预填好的选择屏幕参数快照"。

有一个非常关键的坑,在这里必须强调:如果这个作业是周期性执行的,比如每天跑、每月跑,变式里的日期参数千万不要写死。

举个例子,你做了一个月结汇总程序,里面有个"报表期间"字段。第一次配置的时候,你顺手填了2024年12月,存成变式。这个作业每月1号跑,就算跑一年,它永远不会自动变成2025年1月。每次用的都是2024年12月,数据永远对不上。正确做法是,在变式里把日期字段的取值设置为系统动态参数,比如&DATE(当天日期)、&TIME(当前时间)、&DAY(当日),让系统在每次作业启动时自动取当天的时间。保存变式的时候,字段值框里直接填这些系统变量字符就行。

所以,建作业之前先去确认:程序有没有变式?变式里的日期是不是动态的?变式的执行用户和作业执行用户是否都具备该程序权限?这几件事没有落实之前,作业建了也是白建。

2.2 权限对象:S_BTCH_JOB、S_BTCH_ADM、S_BTCH_NAM缺一不可

很多新人遇到的情况是:作业名填好了,程序也填好了,一点保存,系统提示"作业不是以当前用户创建的"或者干脆报权限不足。这不是系统故障,而是后台作业的权限管控没放开。

SAP对后台作业有一套独立的权限对象体系,最核心的有三个:

第一个是S_BTCH_JOB,这是作业操作的基础权限,几乎所有的作业操作都离不开它。它里面包括ACTION字段,可授权的操作类型有创建、修改、删除、释放、查看日志等。很多项目上只授权了创建、修改,没给释放权限,结果作业建好了但无法释放,卡在已计划状态。

第二个是S_BTCH_NAM,这个是限制作业名的。比如说,你想约束只有特定用户才能创建以ZMONTHLY开头的作业,就用它来控制。

第三个是S_BTCH_ADM,这是更底层的管理员权限,一般给basis用。普通顾问被授权到S_BTCH_ADM的情况不多,但是一旦作业涉及覆盖其他用户的作业、删除他人作业、跨用户操作时,这个权限就会冒出来。

除了这几个,程序本身的执行权限也必须是通的。这里有个很隐蔽的问题:作业是用某个用户身份在后台运行的,不是用创建人的身份。如果作业的执行用户对程序没有权限,作业一样会失败。很多项目上会出现"我建作业、用我的账号测没问题,但放到后台跑就报错",排查到最后发现,后台作业的执行用户根本没有S_PROGRAM或变式相关的权限。

2.3 作业类和目标主机:影响的是资源,不是能不能跑

SM36界面里有两个字段,经常被随手一填就忽略:作业类(Job Class)和目标主机(Target Server)。

作业类是一个资源优先级的概念,SAP里分A、B、C三级。A级最高,会占用更多的后台工作进程配额,跑得快;B是正常级,适合大多数报表和批量任务;C级最低,通常给一些不紧急的、长时间的任务。实际配置时,不建议所有作业都堆在A级,因为A级作业太多会让高优先级进程全被占满,导致其他作业排队时间暴长。月结作业可以用A,日常数据抽取用B就够了。

目标主机是指定作业在哪台应用服务器上跑。如果系统里有多台应用服务器,不指定则由SAP自动选择。这个字段平时没事,但当你发现作业只在特定主机上执行时,就要考虑是不是当时有人顺手把服务器名固定了。尤其是在做过系统拆分、服务器扩容的项目上,旧的目标主机名可能早就失效,作业就会一直挂在"已计划"或者执行时报"主机不存在"。

3. SM36创建定时作业的完整操作路径:从命名到最后保存

3.1 进入SM36,先把作业名和属性定义清楚

操作开始。输入事务代码SM36,回车。SAP会进入后台作业定义界面。新版系统可能会先弹出作业向导(Job Wizard),你可以在向导中选择关闭它,直接用传统方式编辑,免得被一步步牵着走。

第一步是填作业名。作业名的命名规范,强烈建议项目组提前定好,比如"ZMM_DAILY_STOCK_0001""ZFI_MONTH_END_01"这种。命名好的作业在SM37监控列表里一眼就能看出是干什么的,比一堆"BATCH001"好太多。作业名长度限制一般是32位,别超。

接着填写作业类,一般取默认B。如果业务上对时间要求严格,可以选A。目标服务器这一栏按上一条说的,除非有特殊要求,否则先留空,让系统自动选。

这里还要提一下"用户"字段。作业执行用户在后台会作为运行身份。运维场景中,最好让作业的执行用户归到统一的服务账号,而不是挂在某个人名下。万一员工离职、账号被锁,他名下的作业全都会出问题,这是很多月结翻车事故的根源之一。

3.2 定义作业步骤:程序和变式的组合

作业属性填完后,进入步骤维护区域。在步骤表格里新加一行,点击"插入步骤",然后选择步骤类型。最常见的"ABAP程序",选中后在下面的程序名框里输入要执行的程序。

接下来是关键:在程序名后面的变式字段里,用F4选择或直接输入变式名。这一步没做对,作业跑起来会直接使用程序的默认值,取数的逻辑完全走样。变式不存在的话,SAP会提示"变式不存在",同时会问你要不要马上创建。如果遇到这种情况,按2.1的方法先到SE38前台界面把变式建好,然后再回来挂到作业上。

在步骤细节里还可以设置Spool参数(打印参数)。如果这个作业会产生报表列表输出,建议在这里指定一个输出设备(比如LP01或者CANCEL),并且给Spool清单起一个有意义的标题,这样在SP01假脱机管理里就比较容易区分。如果一个作业每天跑、输出一大堆,又没人看,完全可以设置为不保留输出,或者输出到系统日志级别,避免占满spool空间。

3.3 设置开始条件:立即、单次、周期怎么选

步骤设置完了,点击保存按钮。没有设置开始时间的作业保存不了,此时SAP会弹出"开始时间"条件窗口。

在这个窗口里有几个默认标签页。第一是"立即",就是保存完马上运行一次。第二是"日期/时间",指定一个固定时间点运行,适合跑一次性任务。第三是"周期作业",也是我们设置定时作业的主要关注点。

周期作业下拉里,一般会提供每日(Daily)、每周(Weekly)、每月(Monthly)和其他周期(Other period)几种选项。选Daily,填上每天执行的时间点即可。选Weekly,可以勾选周一至周五中需要执行的工作日。选Monthly,则需要配置每月的第几天、以及遇到30、31或月末时的处理方式。

这里特别提一下"其他周期"的用法。它由"周期值(Period Value)"和"周期单位(Period Unit)"组成。周期值填数字,周期单位可选分钟、小时、天、周、月等。比如你要让作业每隔6小时跑一次,就填周期值6,周期单位小时。要隔4天跑一次,就填周期值4,周期单位天。真正的工作场景里,"每两个小时轮询一次接口数据"这种需求,用其他周期实现是很常见的。

周期作业还有一个"超出时间"(Drift)或者叫"变化窗口"的概念,不同的SAP版本叫法不一样,核心意思是允许作业在原本计划时间前后一定范围内波动。如果你的作业对时间要求可以放宽,就可以设置一个漂移窗口,这样系统调度起来更灵活,不容易因为瞬间并发导致作业压死。保守起见,非关键作业我都建议留一点漂移余量。

3.4 一个完整的例子:月度库存报表作业

拿一个实际例子串一下流程。假设要配置一个每月最后一个工作日的下午六点运行的库存报表程序ZMM_STOCK_REPORT。

变式ZMM_STOCK_END里把公司代码、库存地点都填固定,日期字段用&DATE或月底日期动态参数,保存好。在SM36界面填作业名ZMM_MONTHLY_STOCK_1,作业类B,目标服务器留空。步骤指向程序ZMM_STOCK_REPORT,挂变式ZMM_STOCK_END。开始条件选周期作业,Monthly方式,选择每月的"最后一天"或"最后工作日",时间填18:00:00。保存作业,系统回到SM36初始界面,作业已经列在待释放清单里。再用SM37确认状态是已计划(Scheduled),等后台调度器释放。

跑几次之后,建议多看一眼SM37的作业日志,确认变式里的动态日期真的按预期更新了,再把这个作业纳入正式的月度运维清单。

4. 作业不跑、跑挂了怎么查:SM37状态解读与常见故障修复

4.1 SM37的状态一眼看懂

后台作业出问题,绝大多数时候打开SM37就能定位一大半。SM37初始界面有筛选条件:作业名、用户名、日期范围、状态。默认只显示当前用户的作业,如果你是排查所有人跑挂的作业,记得把用户改选为"所有用户"。

SM37列表里每一行就是一次作业执行。看状态栏,SAP后台作业基本有这么几种状态需要掌握:

  • 已计划(Scheduled):作业还没被释放。可能原因:调度器没扫描到它,或者作业的释放时间还没到。
  • 已释放(Released):调度器已经批准它运行,正在等待后台工作进程。
  • 就绪(Ready):它排上队了,但系统里暂时没有空闲的后台进程给它跑。
  • 运行中(Running/Active):正在执行,在SM50里能看到对应的后台进程。
  • 已完成(Finished):正常跑完,注意"正常跑完"不代表"业务结果正确"。
  • 已取消(Canceled):程序异常终止,需要看作业日志确认根因。

这几种状态的切换逻辑,我在第一章节就讲过,排查的时候对应去查就行:卡在已计划查调度和目标主机,卡在已释放/就绪查后台进程资源,已取消查作业日志。

4.2 常见故障和对应的处理方式

我在项目上遇到过的高频故障,整理成一张表:

故障现象通常原因处理方向
作业一直停留在已计划目标服务器不可用RZ04检查应用服务器状态
作业状态变成已取消程序异常、变式参数无效看作业日志定位ABAP报错
作业状态正常但没效果变式里的参数是旧的、写死的检查变式动态日期和参数
作业日志为空日志写入失败或spool被清检查SM37日志存储、SP01
没有权限释放作业S_BTCH_JOB的ACTION缺RELE补授权或让basis释放
作业运行极慢后台进程不足SM50看进程占用,适当加压进程

这些表里的每一条,背后我基本都踩过。最典型的是"作业看起来Finished但数据根本没更新"。第一次遇到这种问题,我也被唬住了。当时用户说每天早上的客户余额报表出不来数,我去SM37看,作业状态明明是Finished。后来点开作业日志,程序日志里只有一句话:程序未找到变式。仔细查才发现,作业里的变式名填的是VARIANT_OLD,而前台实际保存的变式是VARIANT_NEW,名字差一个字母。后台作业按作业步骤里的变式名去找,找到了一个不存在的变式,程序加载失败但作业本身异常退出后状态还是标了Finished。这里我要提醒:对于作业状态,SAP属于"业务状态",日志状态才是"真实状态",一定要点开日志看。

4.3 排错务必按这条链路走

很多时候群里朋友发来一句"作业挂了,怎么查",光凭经验猜效率太低。我的做法是固定按链路排查,从头到尾走一遍:

打开SM37,选对所有用户、相关日期,找到目标作业,点开作业日志。这是第一步,也是最重要的一步。日志里会明确给出ABAP程序报错的位置、短转储信息或者数据库锁的提示。

第二步,如果日志没内容或者内容很干净,就去看程序本身。到SE38打开程序代码,检查是不是最近有传输变更改动了程序,导致变式参数结构不兼容。很多后台作业是在月底跑,而程序在月初有人调整过,月底才暴雷,中间隔了二十多天,人和记忆都对不上。

第三步,去查变式。SE38对应的程序界面,进变式维护,核对当前作业步骤里的变式名和参数,确认变式存在、用户有执行权限。

第四步,查基础设施。SM50看后台进程够不够,RZ04看服务器状态,SM37看最近有没有一大批作业在同时排队的现象。别小看这一步,很多作业跑挂其实就是资源不够,被后面的作业抢了进程。

第五步,看短转储。在事务代码ST22里查看ABAP短转储记录,这种记录通常会保留最近一段时间的dump,里面能定位到具体哪行代码抛异常、哪个数据库操作失败。

这套链路走完,90%的作业问题都能定下根因。剩下10%,可能是业务数据本身的问题,比如主数据缺失、凭证被锁,这就得结合业务逻辑继续用debug方式深挖。

5. 项目上当进阶功能用:作业链、事件触发和BAPI创建作业

5.1 作业链:让A作业跑完再自动跑B作业

实际的月结流程,很少只有一个程序在跑,通常是"先跑A汇总,再跑B分摊,最后跑C生成凭证"。这样的流程如果靠人工一个个去盯,太费人了。

SAP后台作业支持定义后续作业。在SM36里编辑作业时,找到后续作业相关入口(不同版本菜单位置略有差异),添加后续作业和触发条件。触发条件有三个方向可选:无条件执行、仅当上一作业成功时执行、仅当上一作业失败时执行。做月结时,A成功才跑B,B成功才跑C,只要有一环失败,后边都不触发,这正好符合业务上"中间出错就不能继续"的原则。

这里也有一个常见坑:后续作业设置完成后,务必要为后续作业也定义好作业步骤和开始条件。否则系统会提示后续作业无效,跑链的时候静默跳过,让你以为链断了。后续作业本身可以被前面作业"唤醒",但它也得有自己的执行用户、程序和变式。

作业链跑起来之后,SM37里一般能看到整条链的关联关系。我习惯于在看板视图里监控整个链的状态,哪一环节失败一目了然。

5.2 事件触发:不用看时钟,用业务信号启动作业

除了时间驱动,SAP还有一种作业启动方式叫"事件驱动"。作业不按钟点执行,而是等待一个"事件"发生才启动。

事件的管理有两块:SM62维护事件目录(Event Catalog),SM64用来触发事件。事件的本质就是一个内部触发器字符串,可以带参数。比如程序A跑完最后一行代码时,通过BAPI_SYSTEM_EVENT_TRIGGER或专用函数触发一个名为"ZEVENT_MONTH_END_DONE"的事件,作业B在开始条件里选择"等待事件ZEVENT_MONTH_END_DONE",这样只要A事件一触发,B作业就会自动启动。

这种方式最大的好处是把作业间耦合从"时间"变成了"业务结果"。A和B不再需要预估运行时间,也不用担心A没跑完B就开始了。对流程敏感、时效性强的业务,比如从采购收货触发凭证生成、销售订单释放后触发后续价格更新,事件触发比固定时间点可靠得多。

简单提一句外部作业(External Job),它和前台程序关系不大,主要是在RZ01里调度操作系统外部命令、把任务交给系统外部的脚本去执行。项目上主要用于和文件服务器、操作系统批处理脚本对接,需要小心权限校验,非必须不要优先引入。

5.3 用BAPI自动创建作业,做运维自动化

如果系统里有几十上百个作业要统一创建、统一修改开始时间,手工一个个开SM36去点,效率非常低,而且容易漏。SAP提供了标准的作业BAPI,可以在ABAP程序里批量创建后台作业,也可以集成到自己的运维工具里。

核心函数是三个:BP_JOB_OPEN(打开并创建作业)、BP_JOB_SUBMIT(添加作业步骤)、BP_JOB_CLOSE(设置开始条件并关闭作业定义)。

用ABAP调用的一个最小示例:

DATA: lv_jobname TYPE bapiname-jobname, lv_jobcount TYPE bapicount-jobcount. lv_jobname = 'ZFI_BATCH_CREATE_001'. CALL FUNCTION 'BP_JOB_OPEN' EXPORTING jobname = lv_jobname IMPORTING jobcount = lv_jobcount. CALL FUNCTION 'BP_JOB_SUBMIT' EXPORTING jobcount = lv_jobcount jobname = lv_jobname report = 'ZFI_CREATE_POSTING' variant = 'Z_FI_MONTH_END' EXCEPTIONS OTHERS = 1. CALL FUNCTION 'BP_JOB_CLOSE' EXPORTING jobcount = lv_jobcount jobname = lv_jobname strtdate = '20250101' strttime = '010000' periodic = 'X' EXCEPTIONS OTHERS = 1.

这段代码的逻辑是:先开一个名为ZFI_BATCH_CREATE_001的作业,把程序ZFI_CREATE_POSTING和变式Z_FI_MONTH_END挂上去,最后设定从2025年1月1日凌晨一点开始,周期执行。周期参数'periodic'传X表示这是一条周期作业,周期规则还可以在BP_JOB_CLOSE里补充传入事件和时间条件。

用BAPI做作业自动化的好处是,作业创建的参数可以被放到配置表里,由前台维护界面控制,真正做到了运维动作标准化。比如我给客户做过一个简单的作业批量管理程序,用一张自定义配置表存作业名、程序、变式、周期值,主界面里填一条,程序跑一遍自动调用BAPI把对应作业建好。从源头上杜绝手工点错、填错的问题。

最后说一个我自己的习惯:凡是周期作业,我通常在作业名里固定一段标识符,注明是"每日D""每周W""每月M",比如ZFI_M_GL_CLOSE_01,一眼可见是月度总账结账作业。在SM37里筛选时,用作业名前缀加日期范围就能快速捞出目标作业。这个小习惯在项目后期很有帮助,尤其是月末集中执行几十个作业的时候,能省掉大量重复核对的时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询