最近在做一线的工作,要写一个脚本 实现一些功能,发现shell的基础知识有点薄弱,借机会恶补了一下。目录结构如下,
ubuntu@ip-172-31-37-254:~/he pwd/home/ubuntu/heubuntu@ip1723137254: /he ls
Dockerfile run.sh test.sh

Introduct several ways that the script “run.sh” calls another script “test.sh”.
Different way will produce different processes in Container.
Focus on line 3 in script “run.sh”.
Way 1,
. ./test.sh & or source ./test.sh &</br>
Excute “ps -ef” in container,then

UID        PID  PPID  C STIME TTY          TIME CMD


root         1     0  0 03:48 ?        00:00:00 /bin/bash /run.sh
root         5     1  0 03:48 ?        00:00:00 /bin/bash /run.sh
root         9     0  0 03:48 ?        00:00:00 bash
root       806     5  0 05:48 ?        00:00:00 sleep 100
root       816     0  2 05:49 ?        00:00:00 bash
root       824     1  0 05:49 ?        00:00:00 sleep 10
root       825   816  0 05:50 ?        00:00:00 ps -ef

说明: & 代表后台新启动一个子进程Pid=5,执行
然后在test.sh中 又产生一个子进程 pid=806 执行 sleep 100
最后 回到run.sh中,进程1 继续后续循环,产生一个子进程pid=824 执行sleep 10
Way 2,
source ./test.sh or . ./test.sh </br>
Excute “ps -ef” in container,then

root@90091c73f239:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 06:29 ?        00:00:00 /bin/bash /run.sh
root         5     1  0 06:29 ?        00:00:00 sleep 100
root         6     0  4 06:30 ?        00:00:00 bash
root        14     6  0 06:30 ?        00:00:00 ps -ef

说明:由于test.sh 没有后台执行,中有死循环,所以该指令没有新产生子进程,并且不退出,
run.sh中的后续指令比如“sleep 10” 没有被执行。
Way 3,
exec nohup ./test.sh &</br>
Excute “ps -ef” in container,then

root@62e826443205:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  1 06:43 ?        00:00:00 /bin/bash /run.sh
root         5     1  0 06:43 ?        00:00:00 /bin/bash ./test.sh
root         7     5  0 06:43 ?        00:00:00 sleep 100
root         8     1  0 06:43 ?        00:00:00 sleep 10
root         9     0  9 06:43 ?        00:00:00 bash
root        17     9  0 06:43 ?        00:00:00 ps -ef

说明:
& 后台运行子进程,产生pid=5
pid=5 产生子进程 pid=7 sleep 100
有子进程在运行,即使子进程中有死循环,也不会影响主进程的后续执行。
Way 5,
exec nohup ./test.sh </br>
Excute “ps -ef” in container,then

root@421ddeaf1aac:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 06:48 ?        00:00:00 /bin/bash ./test.sh
root         5     1  0 06:48 ?        00:00:00 sleep 100
root         6     0  1 06:49 ?        00:00:00 bash
root        15     6  0 06:49 ?        00:00:00 ps -ef

说明:对比way 3 and 4,说明 exec 、nohup都不会产生新的子进程,而是在主进程中执行,
进入第一个死循环 sleep 100,所以不会继续后续代码sleep 10 的执行。
只有一个主shell在运行
Way 5,
sh ./test.sh </br>
Excute “ps -ef” in container,then

root@7f11956d36a0:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 06:37 ?        00:00:00 /bin/bash /run.sh
root         5     1  0 06:37 ?        00:00:00 sh ./test.sh
root         6     5  0 06:37 ?        00:00:00 sleep 100
root         7     0  4 06:37 ?        00:00:00 bash
root        15     7  0 06:37 ?        00:00:00 ps -ef

说明: 一个脚本中 调用“sh” 执行另一个脚本,会产生子进程 pid=5
“sh test.sh” 没有后台执行,又有死循环“sleep 100”,将不退出,
故run.sh的后续指令没有被执行。

结论: & 作用 后台执行,会产生子进程
exec 、nohup 、source、.不产生子进程
sh 产生子进程 ./ 也产生子进程-并且该文件必须有可执行权限

source filename 与 sh filename 及./filename执行脚本的区别在那里呢?
1.当shell脚本具有可执行权限时,用sh filename与./filename执行脚本是没有区别得。./filename是因为当前目录没有在PATH中,所有”.”是用来表示当前目录的。
2.sh filename 重新建立一个子shell,在子shell中执行脚本里面的语句,该子shell继承父shell的环境变量,但子shell新建的、改变的变量不会被带回父shell,除非使用export。
3.source filename:这个命令其实只是简单地读取脚本里面的语句依次在当前shell里面执行,没有建立新的子shell。那么脚本里面所有新建、改变变量的语句都会保存在当前shell里面。

举例说明:
1.新建test.sh脚本,内容为:A=1
2.然后使其可执行chmod +x test.sh
3.运行sh test.sh后,echo AA=1shell4../test.sh5.sourcetest.sh.test.shecho A,则会显示1,说明A=1的变量在当前shell中

进程号: &产生的子进程 挂在pid=1的进程下面
sh产生的子进程 为顺序cpu 新调度产生的
杀掉子进程,父进程仍存在

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐