Shell脚本中的set -m命令有什么作用?附代码示例
set -m 在示例Shell脚本中的作用 你之前了解的设置位置参数只是set命令的用法之一,这个Shell内置命令有两类核心功能:
- 传入不带横杠的普通参数时,为
$1、$2等位置变量赋值,就是你之前熟悉的用法 - 传入带横杠的选项参数(比如
-m、-e、-u)时,用来切换当前Shell的运行时开关,修改Shell默认行为
-m 选项的核心行为
-m是作业控制(Job Control)的启用开关:
作业控制模式默认只在交互式Shell(即用户手动打开终端输入命令的环境)下自动开启,执行脚本时的非交互式Shell默认关闭该功能。
执行set -m强制开启作业控制后,Shell会产生几个关键的行为变化:
- 所有通过
&放到后台启动的进程,会被分配独立的进程组ID,不再和父Shell共享同一个进程组 - 后台进程不再默认忽略SIGINT(按下Ctrl+C触发)、SIGTERM等终止信号,和前台进程一样响应信号规则
wait命令可以可靠等待后台进程退出,准确捕获进程的退出状态码,不会出现漏等、错等的问题- 父Shell退出时可以向整个关联进程组发送终止信号,不会出现父脚本已经退出、后台子进程变成孤儿进程残留运行的情况
对应到你贴的脚本场景
脚本中set -m写在( )代码块的外层,作用是让后续启动的子Shell(括号包裹的代码会在独立的子Shell环境中执行)继承作业控制开启的状态。
括号内的逻辑会先后启动两个后台bash脚本,中间用wait等第一个后台任务执行完成后再启动第二个。如果省略set -m,在非交互式的脚本执行环境下会出现几个不符合预期的问题:
- 脚本运行过程中如果用户按下Ctrl+C终止主进程,已经启动的后台脚本不会收到终止信号,会变成孤儿进程继续在后台运行
- 极端场景下
wait无法正确捕获第一个后台进程的退出状态,可能导致第二个脚本提前启动,或者主进程永久卡住 - 脚本执行结束后未跑完的后台进程会被系统init进程收养,残留不必要的后台进程占用资源
补充说明:你贴的代码中hash值判断用-ne属于写法错误,-ne仅支持整数比较,对比字符串哈希值应该使用!=,这个问题和set -m的作用无关,是脚本本身的小缺陷。
内容的提问来源于stack exchange,提问作者Lawhatre
相关产品推荐
相关产品推荐

