bash 中 $(cmd1|cmd2)会在当前进程下创建子进程?

发布于 2022-09-05 23:40:36 字数 2906 浏览 44 评论 0

问题发现

这几天写shell脚本时,发现$(cmd1|cmd2)会创建子进程

脚本如下:

#!/bin/bash
echo -e '\n\033[32;1m-----------\033[0m'                              
echo "The name of this file is $(basename $0)."                       
echo "The pid of this program is $$."                                 

echo -e '\n\033[32;1m---- 0 ----\033[0m'                              
echo -e '\033[33;1mCMD: ps -ef|grep "aaaa.sh"|grep -v grep\033[0m'    
ps -ef|grep "aaaa.sh"|grep -v grep 

echo -e '\n\033[32;1m---- 1 ----\033[0m'                              
echo -e '\033[33;1mCMD: ps -ef|grep "aaaa.sh"|grep -v "bbbb"|grep -v grep\033[0m'                                                            
ps -ef|grep "aaaa.sh"|grep -v "bbbb"|grep -v grep                     

echo -e '\n\033[32;1m---- 2 ----\033[0m'                              
echo -e '\033[33;1mCMD: pgrep -a "aaaa.sh"|grep -v "bbbb"\033[0m'     
pgrep -a "aaaa.sh"|grep -v "bbbb"  

echo -e '\n\033[32;1m---- 3 ----\033[0m'                              
echo -e '\033[33;1mCMD: pgrep -a "aaaa.sh"|grep -v "$$"\033[0m'       
pgrep -a "aaaa.sh"|grep -v "$$"    

echo -e '\n\033[32;1m---- 4 ----\033[0m'                              
echo -e '\033[33;1mCMD: output=$(ps -ef|grep "aaaa.sh"|grep -v "bbbb"|grep -v grep)\033[0m'                                                  
output=$(ps -ef|grep "aaaa.sh"|grep -v "bbbb"|grep -v grep)           
echo -e "$output"                  

echo -e '\n\033[32;1m---- 5 ----\033[0m'                              
echo -e '\033[33;1mCMD: output=$(ps -ef|grep "aaaa.sh"|grep -v "$$"|grep -v grep)\033[0m'                                                    
output=$(ps -ef|grep "aaaa.sh"|grep -v "$$"|grep -v grep)             
echo -e "$output"                  

echo -e '\n\033[32;1m---- 6 ----\033[0m'                              
echo -e '\033[33;1mCMD: output=$(pgrep -a "aaaa.sh"|grep -v "bbbb")\033[0m'                                                                  
output=$(pgrep -a "aaaa.sh"|grep -v "bbbb")                           
echo -e "$output"                  

echo -e '\n\033[32;1m---- 7 ----\033[0m'                              
echo -e '\033[33;1mCMD: output=$(pgrep -a "aaaa.sh"|grep -v "$$")\033[0m'                                                                    
output=$(pgrep -a "aaaa.sh"|grep -v "$$")                             
echo -e "$output"                  

echo -e '\n\033[32;1m---- 8 ----\033[0m'                              
echo -e '\033[33;1mCMD: output=$(pgrep -a "aaaa.sh")\033[0m'          
output=$(pgrep -a "aaaa.sh")       
echo -e "$output"                  

echo -e '\n\033[32;1m-----------\033[0m'

输出结果

aaaa.sh 输出

疑问

其中的 4、5、6、7项都输出了两个进程,请问这是shell自身的机制吗?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

入怼 2022-09-12 23:40:36

得理解bash解释执行脚本的机制,当执行./aaaa.sh的初始,就已经fork()了一个子进程,这个子进程的父进程是当前登录shell
随着脚本内容的被执行,根据每行命令的不同,又有不同的执行方式:
echo命令属于bash内置命令,它在执行时相当于执行bash内部的一个函数,不创建子进程。
grepps等属于外部命令(不是bash本身内部实现的命令),它们在执行时需要经过fork()execve(),都需要创建子进程。
而bash对管道|又有特殊处理,处于管道两侧的命令,会分别运行于两个子shell(每个子shell都属于原父shell的子进程),不过前一个命令的标准输出会连接到后一个命令的标准输入。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文