1. 先搞清楚SM36跑的是什么:后台作业运行机制
1.1 后台作业与前台程序有什么不一样
每次登录SAP GUI,你在事务码框里敲一个T-code,程序就在你的会话里前台执行,你盯着屏幕等结果,这叫前台运行。你敲的SM36本身也是个前台程序,但SM36干的事,是把别的程序安排到后台去执行。
SM36创建的定时作业完全不同:你把一个程序、一个日期、一个时间告诉系统,系统在后台一个人默默执行,不需要你守在屏幕前,也不用一直占着一个会话。哪个该前台跑,哪个该后台跑?大体上,交互复杂、需要人临时输入的,前台;数据量大、耗时长、逻辑固定、定时重复的,一律塞进后台。比如计提折旧、运行MRP、每天汇总报表、月结外币评估,这些操作动辄跑几十分钟,放前台你得一直占着对话会话,非常浪费。
我碰到过不少顾问,刚接触SAP时总觉得“后台作业”和“前台运行”只是执行位置不同,其实两者连执行会话都是独立的。你在前台跑一个程序,如果你把GUI关了,程序也就中断了。但后台作业不一样,你把作业建好释放之后,哪怕你立刻关机走人,作业到点照样跑,跑完日志照写。这正是定时作业的核心价值:人要下班,业务不能下班。
1.2 Batch进程与SAP逻辑处理流程
后台作业必须通过系统里的批处理进程(Batch Process)来执行。在SAP系统里,你说的“后台作业”,本质上就是调度器(Dispatcher)把一段任务分配给后台工作进程(Dialog Work Process中的批处理类型),进程执行完,把日志和结果写进作业日志和假脱机(Spool)系统。
你不需要管进程到底有多少个,但你要知道它是有数量限制的。如果一个时间点排的作业太多,超过Batch进程数量,系统就会把后面的作业放入队列排队,前面的不跑完,后面的就一直等着。实际项目里最常遇到的现象,就是作业确实在计划时间内触发了,但一直处于“已计划”或者“准备”状态,原因多半是进程排队。
做BASIS的朋友应该清楚,服务器上的“当前进程数”直接决定并发能力。很多小型项目只有三五个后台进程,一到月底结账,各个模块的作业全挤在一起,后面的作业就只能在队列里干等。这时候别慌,先看进程是不是被一个大作业占满了,再决定是等还是调整作业优先级。作为模块顾问,不需要去调参数,但得看得懂这个现象,否则你会在“作业为什么不跑”这个问题上浪费大半天。
1.3 定时作业的典型应用场景
我做过不少项目,后台作业用得最多的场景大概五类:
- 批量数据接口,例如定时从外围系统拉数据、跑RFC接口,常见于SAP与SRM、MES、OA系统对接。
- 批处理报表,每天凌晨算前一天的数据,比如销售日报、库存周转报表。
- 月结年结程序,比如外币评估、物料分类账、资产折旧、成本结算,这些在月末集中跑,一个作业跑完另一个接着跑。
- SAP标准程序调度,比如MRP运行、订单结算、重估库存,都和物料需求计划和生产执行强相关。
- 外部命令或外部程序,比如通过操作系统命令清理日志、压缩文件、调用外部脚本。
这些场景的共同特点就是重复、可预测、时间固定。你稍微花十分钟把作业建好,以后每天就不用再手动敲一遍程序。特别是月结的时候,以前手工一个个T-code跑,一忙就是两三个小时,把流程做成定时作业之后,到了时间自动跑,你只需要第二天早上看一眼SM37的结果,出错再介入。这就是为什么我一直建议项目里尽量把重复性工作作业化。
2. 动手实操:SM36创建定时作业的标准流程
2.1 打开SM36后面前的界面一眼看明白
SM36初始界面其实很简洁。顶部是一个包含多个字段的区段,从上到下分别是作业名、作业类、作业状态、目标服务器,下方就是两个核心标签页:“步骤”和“起始条件”。
很多人第一次打开SM36,不知道从哪开始,其实流程特别固定:先定义一个唯一的作业名,再定义步骤,再定义起始条件,然后保存,完事。作业名建议按规范命名,比如Z_RUN_MRP_DAILY、Z_DEPRECIATION_MONTH_END之类,我见过太多项目用TEST1、JOB2这种名字,到月末根本分不清是哪个作业,最后只能打开挨个看步骤,效率极低。
这里顺带说下“作业类”字段。作业类在SAP里通常用A、B、C来区分优先级,A类优先级最高,C类最低。一般日常报表作业用B类就够了,月结的敏感作业我会设成A类,因为这时候系统忙、进程紧张,得让它优先抢到Batch进程。如果你把所有作业都设成A,那其实等于没有优先级,所以别滥用。
还有一个容易漏掉的字段是“目标服务器”。如果系统是多应用服务器集群,你可以把作业固定在某台服务器上跑。比如某个作业需要读取特定应用服务器的本地文件,那就必须指定目标服务器。大多数情况下留空或者用“服务器组”就行,系统会自动分配。
2.2 第一步:定义作业步骤(选程序、变式、输出设备)
点“步骤”按钮进入步骤定义界面。这里的关键是“用户”和“程序”的组合。系统会让你定义这个作业在哪个用户下运行,然后填程序名,也就是你要运行的ABAP程序、外部命令或外部程序。
这里有一个极其重要的建议:作业运行用户统一用专用服务账号,不要用个人账号。为什么?如果你用自己的账号跑,账号密码过期、被锁、离职删号,作业直接就跪了。而且作业日志会显示成你的名字,如果出问题,审计追查到的是个人。我在一个项目里就遇到过,某财务接口作业因为密码过期,连续三天凌晨没跑,业务早上来问,我们查了半天发现运行用户居然是一个早就不在公司的离职同事,这就是典型的管理漏洞。
在步骤界面里,程序名可以直接填,也可以用搜索帮助查找。你要运行的是ABAP程序,填入程序名;如果是外部命令或外部程序,切换到对应页签。外部命令常用于调用操作系统脚本,比如在Unix服务器上跑一个清理临时文件的命令。这部分需要BASIS配合定义外部命令权限,普通顾问一般不建议直接碰。
这一步最重要的就是“变式”(Variant)。同样的报表程序,你跑今天的和跑昨天的,很多时候只是参数不同,变式就是为了解决这个问题。你可以在创建作业时直接新建变式,也可以先把变式维护好(在SE38或SA38里),到SM36里选。变式一旦定下来,程序每次跑都会按变式里的参数来,不会出现明明连了测试环境却用了生产参数这种低级事故。
顺带说一下,步骤界面里还能设置输出的Spool参数。比如程序输出到打印机的,可以指定输出设备、打印份数。如果业务需要自动打印报表,这个设置就很有用。否则程序跑到最后生成一个Spool请求,没人管它,过几天就被系统自动清理了。
2.3 第二步:设置起始条件(立即执行/定时执行/周期执行)
步骤定义完,点“起始条件”按钮。这里有几个选项我逐个说。
第一是“立即”,就是保存后系统尽最大努力立刻去跑,一般做一些临时补跑或者手动触发时才用。第二是“日期/时间”,指定某年某月某日的某个时间点,作业只跑一次。这种一般用于一次性任务,比如你下周五要跑一次特殊报表。第三是“周期作业”,它是真正的定时器,能设定从某时刻开始,每间隔多少时间运行一次。
这里要提醒的是:在SAP里,精确到秒的调度说实话没必要,绝大多数周期作业,你设到分钟级就够了。系统的作业调度最小单位是分钟,你可以设成每30分钟跑一次,或者每6小时跑一次。如果业务要求必须精确到秒,你需要额外检查应用服务器与数据库服务器的时间同步,否则你设定的“08:00:00”和实际出发的“08:00:十几秒”会有偏差,虽然通常不影响结果,但扣时间逻辑的程序就必须注意了。
起始条件界面里还有“作业后运行框架”等高级选项,其中包含“其它作业”和“事件”调度。意思是可以让这个作业在另一个作业结束后触发,或者在某个事件发生时触发。这部分我会在后面进阶部分展开,新手第一阶段先掌握日期时间和周期就够用。
2.4 第三步:设置周期(每日/每周/每月自动化周期)
周期作业设置界面里有两个组成部分:日期和周期。日期定义在哪天开始运行、在哪天结束,周期定义每隔多久跑一次。
这里最容易踩的坑是很多人只知道填“周期”,不知道用“标准周期”。在SAP里,有一个“标准周期”按钮,点开之后弹出“每日/每周/每月/其他周期”的快捷模板。你想每天跑,选“每天”,系统会自动在“周期值”里写一个时间间隔;你想每个工作日跑,就得手工决定是否排除周末。
举个例子,我想让作业每天凌晨2点跑一次。你可以选标准周期里的“每天”,它会自动生成一个周期模式,代表“每1天运行一次”,然后你在下面的“开始时间”填02:00:00。如果想每周一早上6点跑,就选“每周”,系统会让你选择星期几。
这里我特别想强调SAP对周期作业有一个隐形的“备份冗余”机制:你创建周期作业时,SAP会默认在周期前自动生成一个冗余作业,下一次运行时间会顺延。有些顾问第一次看到作业列表里多了个状态为“已计划”的作业,名字和你自己的差不多,以为系统错乱了。这个其实非常正常。SAP这么设计是为了保证周期计算的稳定性,不要手动去删那个带Redundancy标记的作业,删了会影响周期自动延续。
另外还要提一句:周期作业的“期间开始”和“期间结束”是两个很容易被忽略的字段。如果你只填了开始日期,没填结束日期,作业会一直周期性跑下去。如果填了结束日期,到了那天之后,作业就静默退场,不报错,SM37里也看不到了。所以每次查看周期作业,都要顺手确认一下结束日期。
2.5 保存作业前的最后检查清单
保存作业之前,按我这几年练出来的习惯,建议过一遍以下检查点:
- 作业名是否规范可辨识。
- 运行用户是否为服务账号,且该账号拥有程序执行权限。
- 变式是否已保存有内容,且变式用户与运行用户是否一致。
- 目标服务器是否指定,尤其多应用服务器集群环境。
- 起始条件是定时还是周期,时间值是否正确。
- 需要输出时是否指定了假脱机输出设备。
这套检查不用太长时间,但能帮你挡住绝大多数低级问题。
我为什么强调变式用户一致?因为变式是按用户保存的,创建变式的用户是A,而作业运行用户是B,B在运行时如果没有该变式的授权,作业会直接报“变式不存在”错误,而这个问题在作业启动前完全看不出来。你只能等作业跑了才发现报错,白浪费一个晚上。很多项目里的作业日志一打开全是红字,十有八九就是这种变式授权问题,排查起来还特别隐蔽。
3. 作业建好了不等于万事大吉:SM37监控与问题排查
3.1 SM37怎么看作业是否正常跑完
定时作业的“定时”只是安排表,真正验证成果总归要回到SM37。SM37是整个后台作业监控的总控室。
打开SM37后,报表选择屏幕里有“作业名”“用户名”“作业状态”等条件,最常用的是按作业名和日期范围筛选。点执行后,你能看到所有符合条件作业的列表,列包括作业名、状态、开始日期/时间、最后运行过程、计划开始时间等等。
判断一个作业跑没跑完,看状态即可:“已计划”表示还没到时间或者正在排队,“已释放/已计划”一般表示已触发等待运行,“完成”表示运行结束,“取消的”表示出问题了,“激活”表示正在运行。真正的超时和异常,往往要通过“运行过程中的步骤”和“作业日志”进一步看。
这里有个小细节:SM37的列表可以双击作业,进入作业定义界面,里面有“作业日志”标签,打开后能看到程序运行时写到日志里的每一条消息,这是排查的第一现场。很多程序会把关键的报错信息写进日志,如果你看到日志里出现红色的消息,基本可以断定程序执行出了问题。
还要记住:作业显示“完成”,不代表业务结果正确。SAP里所谓“完成”只代表程序正常结束时没有崩溃。如果程序逻辑里查不到数据、更新条数为0,它照样正常结束、照样显示完成。所以我一般会在作业后的第二天早上,让业务人员确认一下结果数据,或者写一段简单的SQL去核对关键表里的记录数。
3.2 作业没按计划运行的排查顺序
我在生产中处理“作业没跑”这类工单,一般按这样的顺序排查:
第一,SM37查作业有没有在计划时间被触发。如果作业还是“已计划/释放”,检查Batch进程够不够,不够就等或调优先级。这一步解决的是“排队卡住”的问题。第二,如果作业触发了但很快报错,看作业日志,最常见是程序权限、变式不存在、数据库锁。第三,如果作业显示完成但业务说没效果,去查程序日志和Spool输出,有些程序“作业完成”仅仅是程序正常结束,但里面的数据更新逻辑没满足条件。第四,如果作业当天完全没出现,查是不是有人误删或改了周期设置,以及该作业的“最后运行日期”是否到期。周期作业有结束日期,到了就真的静默退场了,不会报错。
这套顺序看上去简单,但真按顺序查,90%的问题十分钟内能定位。最怕的是不看SM37,直接猜原因,一会怀疑权限,一会怀疑程序被改,实际可能只是进程满了没轮上。
还有一个经常被忽略的地方:某些程序会直接通过SM36创建并释放作业,但程序本身在运行过程中又动态创建了后续作业。这种作业的作业名可能带有动态编号,你在SM37里按业务关键词搜,可能搜不到,还会以为是系统漏了。遇到这种情况,要看主作业的日志,或者查表TBTCO(作业定义表)和TBTCP(作业步骤表),这两个表里记录了所有后台作业的完整轨迹。
3.3 常见的作业状态含义对照
我把日常最常遇到的状态整理成一张速查表,贴在下面。以后看到SM37里诡异状态,先来对一下,能省不少事。
| 状态 | 含义 | 下一步动作 |
|---|---|---|
| 已计划(Released) | 作业已到计划时间,等待后台进程执行 | 检查Batch队列,耐心等待或调整优先级 |
| 激活(Active) | 正在运行 | 正常,等待;太久没结束则查DB锁或评估程序效率 |
| 完成(Finished) | 成功运行完毕 | 结合日志确认数据结果是否真的符合预期 |
| 取消(Canceled) | 运行中断 | 双击查作业日志,定位程序或系统错误 |
| 已计划/正在准备(Scheduled) | 已提交但未触发 | 检查计划起始时间是否在未来 |
| 已解除(Released) | 作业被手动释放 | 看谁释放的,可能被误操作 |
除了这些,我还想提醒一句关于“假脱机”的状态。如果作业生成了Spool输出,但输出设备有问题,作业本身可能显示完成,但Spool状态是“有错误”。假脱机问题通常不影响程序数据更新,但会影响打印报表,需求方如果一直没收到打印件,会来问你怎么回事。排查时别忘了看一眼Spool列表,事务码SP01和SM37里都能看到。
4. 进阶玩法与高频踩坑:作业变式、周期运算、依赖调度
4.1 作业变式:让同一程序用不同参数跑
进阶部分我想先讲变式,因为它是后台作业最被低估的功能。变式(Variant)说白了就是程序参数的“打包”。你打开一个报表程序,选了公司代码、时间区间、输出格式,选完点保存,就能存成一个变式。在SM36创建作业时选择这个变式,作业每次跑起来就会自动用这一套参数。
项目里最常见的做法是:同一个程序按不同公司代码或不同工厂建多个变式,再分别建多个作业。比如生产数据导出程序,华东区一个变式、华南区一个变式,两个作业每天各自跑各自的数据。这样互不干扰,某一个跑挂了只影响一个区域。
操作上有一个入口区别:在程序选择屏幕的工具栏上,“保存变式”按钮可以把当前参数保存成变式。如果你不想进SE38,直接在SA38里运行程序,也可以维护变式。SM36里创建作业时,变式栏旁边有一个新建图标,可以直接跳过去维护,非常方便。
这里我想提醒一个容易出错的点:变式有“仅后台”属性,如果程序里有选择屏幕字段被标记为“仅后台”,前台执行时你看不到它,但后台作业里会用到默认值。有时候作业参数怎么调都不对,很可能就是这个字段的默认值被某个历史变式固定住了。排查方法很简单,在变式维护界面里,把所有字段都显示出来,逐项检查那些你平时看不到的字段值。
4.2 周期作业的“再加一次”与跨期调度
接着说周期作业的一个隐藏机制。SAP创建的周期作业,在作业列表里你会经常看到两个作业,一个是你命名的原周期作业,另一个名字带“RED”或者类似标识的冗余作业,这是系统自动生成的,目的是防止作业周期计算失真。不要手动删掉RED作业,删了周期作业就不会自动继续了。要延长或修改周期,直接在原始作业上改即可,系统会自己重算下次运行时间。
还有跨期调度的问题:如果你建作业时设置的周期是每月1日跑,但作业的结束日期是去年年底,那它今年其实就静默不跑了。这类问题运维人员最容易忽略,因为作业看着还在,名字也在,SM36打开也在,但SM37里现在日期范围内什么都搜不到。判断周期是否有效,最直接的方法是看SM37列表里的“计划开始时间”,如果下一行永远是空的或者停留在很久以前,就要怀疑周期已经终止了。
另外,SAP里对周期作业的“下一次开始时间”计算有一些鲜为人知的规则。比如你设定“每5分钟跑一次”,你可能以为分秒不差,实际上SAP会找到一个最小的整分钟倍数的起始点。这不算漏洞,但在对接外部系统、按时间戳校验数据时,会产生一些微小的偏差,写接口程序时最好允许前后几分钟的容差。
4.3 串行作业与事件调度
有些任务要按顺序来,比如先跑数据导出,再跑数据转换,最后再跑报表。这时候有几种做法:
第一种,在一个作业里把多个步骤挨个加进去。后一个步骤何时启动,由系统按顺序自动接续。这种最简单,两个程序之间没有复杂的依赖关系,只是人工顺序执行。第二种,用“作业后运行框架”,把后续作业设为前一个作业的后续作业,条件是前一个作业运行成功(或取消)后再触发。第三种,用事件调度,程序运行中通过事件(Event)触发另一个作业。优先级和复杂程度从低到高。
我个人的经验是,能在同一个作业里多步骤解决的,就尽量别拆成多作业。拆太多了,依赖关系一旦断掉,排查就是一场灾难。但反过来,如果两个程序的内存占用都很高,又必须串行,拆成两个作业更稳,哪怕它们用同一个Batch进程也不会挤在一起,因为后一个作业必须等前一个完成才触发。
事件调度适合那种“程序内部跑到某个点,才发现需要触发另一个功能”的场景。说白了它是程序级联,需要开发配合写代码触发事件。一般业务排程用不上,如果项目里有人提议用事件调度,先问一句“直接用后续作业行不行”,大多数时候答案是肯定的。
4.4 常见问题与避坑速查表
这个表是我从多个项目教训里总结出来的,基本覆盖了80%的SM36使用问题:
| 现象 | 最常见原因 | 处理建议 |
|---|---|---|
| 作业没跑 | 周期结束日期过期、作业被删、Batch进程不够 | 查SM37计划时间和TBTCO表 |
| 作业重复跑 | 周期值设太小、作业被复制过 | 查“最后运行过程”确认上次运行时间 |
| 作业报错,日志一片红 | 变式不存在、运行用户权限不足、程序更新冲突 | 从第一条红色消息往前倒查 |
| 作业显示完成但数据没更新 | 程序筛选条件无数据、更新逻辑未执行 | 核对业务数据条件和变式参数 |
| 作业找不到 | 作业名是动态生成的、被误删 | 查TBTCO/TBTCP表,按用户和日期搜 |
| Spool有错误 | 输出设备失效、打印格式缺失 | 用SP01查看输出请求状态 |
大家以后遇到类似问题,直接照表排查,基本上能少走很多弯路。不过要记住,这些只能定位“作业层面”的问题,如果程序本身的逻辑有错,后台作业是救不了的,还得回到代码层面去查。
5. 最后说点实在话:我踩过的坑和现在坚持的规矩
最后聊一点个人体会。我最早学SM36的时候,以为把程序、周期、日期填好就完事了,直到有一个月末作业连续两次跑飞,才发现问题出在“运行用户”和“变式用户”因为密码过期导致权限失效。从那以后,我给自己立了三条规矩。
第一,所有生产环境后台作业统一挂到一个专用服务账号上。这个账号不干别的,就是跑后台作业,密码由BASIS统一管理,每季度定期改。跑作业和改密码是分开的两拨人,账号出事不会影响业务用户。
第二,每个作业的说明栏写清楚业务用途、运行频率、责任人。作业名可以简短,但说明栏一定要写全。不然半年后你自己都想不起来这个Z_JOB_001是干嘛用的,更别说新接手的同事了。
第三,定期用SM37列一次全部作业清单,核对周期和最后运行情况。我一般建议每月第一周做一次,不需要花太多时间,但能在问题爆发前发现很多隐患,比如某个周期作业悄悄停了、某个作业已经连着三天报错没人管。
这三点听起来很基础,但在实战里带来的安稳感,比任何花哨技巧都值钱。定时作业这东西,做得好了,业务每天睁眼看到数据是齐的,没人觉得你厉害;做得不好,凌晨的告警群消息会帮你把存在感拉满。希望这篇文章能帮你少踩几个坑,把后台作业这个基本功练扎实,关键时候不掉链子。