Bash中进程替换的执行顺序规则咨询
核心结论
Bash没有明确规定进程替换(>(...))的执行顺序,这些通过进程替换创建的子进程是与主进程(如示例中的tee)异步并行运行的,它们的启动、执行及完成顺序完全由操作系统的进程调度器决定,同时还会受到文件IO操作的竞争影响,因此每次运行的结果可能不一致。
逐个分析示例代码的结果
code1:全追加写模式
所有进程替换中的命令都用>> file-1(追加写入),每个sed处理完输入后会将内容追加到文件末尾。你看到的a_3→a_2→a_1的顺序,只是本次运行中操作系统调度器让三个子进程按这个顺序完成了写入操作。如果多次运行这段代码,你很可能会得到不同的行顺序——因为追加模式下,单一行的写入是原子操作,但进程的执行顺序没有保障。
code2:混合覆盖与追加写模式
第一个进程用> file-2(覆盖写入,会先截断文件),后两个用>>追加。结果中只出现a_1和a_2,没有a_3,可能是第三个子进程的写入被调度器延后,或者在第一个进程截断文件后,第三个进程的写入动作没有及时完成。同样,这个结果也不固定,多次运行可能会出现包含a_3的情况,或者行顺序变化。
code3:全覆盖写模式
所有进程都用> file-3(覆盖写入),每次使用>打开文件时都会截断清空现有内容。最终文件里只保留了a_1,说明本次运行中第一个sed进程是最后完成截断并写入的那个进程。但如果重复运行,你可能会得到a_2或a_3——因为谁最后执行覆盖写入操作,谁的内容就会留在文件里,而这个顺序完全由调度器决定。
实践建议
如果你的业务逻辑依赖固定的执行顺序,绝对不要使用进程替换,应该改用串行执行的方式(比如用管道串联命令,或者分步骤顺序执行),这样才能保证操作的顺序性和结果的一致性。
内容的提问来源于stack exchange,提问作者tom

