# 当前login-shell的进程PID.
root@37C:~# echo $$
3016
# 测试脚本:
root@37C:~# cat run.sh
#!/bin/bash
# 获取执行shell脚本的非交互shell的PID.
echo $$
######
echo "test1:-------------------------"
ps -ef | grep `echo $$`
echo "test2:()-----------------------"
( pwd;echo $$; ps -ef|grep `echo $$`; )
echo "test3:{}-----------------------"
{ pwd; echo $$; ps -ef | grep `echo $$`; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
# 脚本执行结果:
root@37C:~# ./run.sh
# 或者
root@37C:~# bash run.sh
11299
test1:-----------------------
root 11299 3016 0 15:26 pts/4 00:00:00 /bin/bash ./run.sh
root 11300 11299 0 15:26 pts/4 00:00:00 ps -ef
root 11301 11299 0 15:26 pts/4 00:00:00 grep 11299
test2:()-----------------------
/root
11299
root 11299 3016 0 15:26 pts/4 00:00:00 /bin/bash ./run.sh
root 11303 11299 0 15:26 pts/4 00:00:00 /bin/bash ./run.sh
root 11305 11303 0 15:26 pts/4 00:00:00 grep 11299
test3:{}-----------------------
/root
11299
root 11299 3016 0 15:26 pts/4 00:00:00 /bin/bash ./run.sh
root 11307 11299 0 15:26 pts/4 00:00:00 ps -ef
root 11308 11299 0 15:26 pts/4 00:00:00 grep 11299
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
结果分析:
1). 交互式login-shell的进程ID为:3016。
2). login-shell(3016)派生出非交互式的shell执行进程(11299),该进程负责解释run.sh脚本里面的命令并执行。
3). 11299(脚本执行进程)负责逐行执行脚本:遇到内置命令直接在当11299进程中执行,遇到可执行程序就fork出新的子进进程来执行。
4). test1的结果:进程 ps(11300 ) 和 grep (11301 )都是执行shell 11299 进程派生的子进程。
5). 11299(脚本执行进程)扫描到( cmd1;cmd2;) 语句群时,会再派生一个ID为11303 子shell负责执行( cmd1;cmd2;)内的命令和语句:11303 逐行扫描()中的语句,按照步骤3的规则进行处理:进程号11305 (grep),还有另一个进程(ps),都是11303 派生出的子进程,ps子进程此处没有显示出来。
6). 11299(脚本执行进程)扫描到{ cmd1;cmd2;} 语句时,不会新派生子shell,直接使用当前进程11299进行负责逐行解释执行脚本。
采用source方式执行脚本:
root@37C:~# echo $$
11389
# 可以看到,并不会派生子shell解释脚本。
# 而是直接使用login-shell进行解释。
root@37C:~# source run.sh
# 或者
root@37C:~# . run.sh
11389
test1:-----------------------
root 11389 11388 0 15:54 pts/4 00:00:00 -su
root 11451 11389 0 16:15 pts/4 00:00:00 ps -ef
root 11452 11389 0 16:15 pts/4 00:00:00 grep --color=auto 11389
test2:()-----------------------
/root
11389
root 11389 11388 0 15:54 pts/4 00:00:00 -su
root 11454 11389 0 16:15 pts/4 00:00:00 -su
root 11456 11454 0 16:15 pts/4 00:00:00 grep --color=auto 11389
test3:{}-----------------------
/root
11389
root 11389 11388 0 15:54 pts/4 00:00:00 -su
root 11458 11389 0 16:15 pts/4 00:00:00 ps -ef
root 11459 11389 0 16:15 pts/4 00:00:00 grep --color=auto 11389
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
总结:
1):在当前shell中执行内部命令不会派生子shell。
2):在当前shell中执行外部命令或脚本时会派生子shell,所以这时命令的执行不会影响当前shell环境。
3):要想在当前shell中执行脚本,而不派生子shell,可以使用 . 和source 命令 执行,会影响当前shell的环境。
4):./run.sh = bash ./run.sh 当前shell会派生子shell执行脚本文件,脚本的执行不会影响到当前shell环境。
5):. ./command.sh = source ./command.sh 直接在当前shell中执行脚本,脚本的执行回影响到当前shell环境。
参考文献:
1.原文地址 https://blog.youkuaiyun.com/beautysleeper/article/details/52586712