before_script/after_script与script命令的执行关联及底层运行机制技术问询
关于before_script、script、after_script的执行顺序与底层机制解析
我来给你捋清楚这几个环节的执行逻辑和底层细节,帮你彻底搞明白~
一、严格的执行顺序
这三者的执行顺序是固定且严格的:
- 首先完整执行
before_script中定义的所有命令(按你编写的顺序依次跑完) - 接着执行
script阶段的命令(同样按顺序执行) - 最后执行
after_script的命令,而且不管script阶段是成功完成还是报错终止,after_script都会被触发(除非作业被强制终止,比如超时、手动取消)
举个直观的例子:如果before_script有2条命令,script有3条,after_script有1条,那执行流程就是:before1 → before2 → script1 → script2 → script3 → after1,中间不会跳步。
二、底层运行机制与进程存活问题
主流CI系统(比如GitLab CI、GitHub Actions这类)的底层逻辑是这样的:
- 共享执行上下文:
before_script、script、after_script的所有命令都在同一个执行环境里运行——比如同一个Docker容器、同一个虚拟机的shell会话,共享工作目录、环境变量、已安装的依赖等上下文信息。 - 统一的shell进程:CI的执行器(比如runner)会把这三个阶段的命令拼接成一个完整的shell脚本,然后在同一个父shell进程里执行这个脚本。也就是说,所有命令都是这个父shell的子进程,包括你在
before_script里启动的后台进程。
那你关心的「后台命令是否会在before_script结束后终止」的问题:
如果你在before_script里启动了一个后台进程(比如./my-long-running-service &),这个进程不会在before_script阶段结束后就被终止——它是整个job的父shell的子进程,只有当整个job的shell会话彻底结束(也就是after_script执行完毕,父shell退出)的时候,它才会收到终止信号(除非你用nohup或disown让它脱离父shell控制,但CI环境里一般不需要这么做,因为job结束后整个环境都会被清理)。
举个实际场景:你可以在before_script里启动Redis后台服务,然后在script里跑依赖Redis的测试用例,最后在after_script里清理测试日志——整个过程中Redis会一直运行,直到after_script执行完、整个job结束才会被终止。
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

