Chinaunix

标题: 这个都不清楚就别说会用linux [打印本页]

作者: wslmyb    时间: 2010-09-10 12:36
标题: 这个都不清楚就别说会用linux
转到这个
http://linux.chinaunix.net/bbs/thread-1170850-1-1.html
作者: l.darkfire    时间: 2010-09-10 14:01
"说到底最不明白的是2点
1 source是否新开了一个进程。
  没开的说法:看现象1中的102部分
  开了的说法:看现象1中的104部分
  也许这个问题应该结合是否为前台后台等综合讨论。
2 所谓的&是否受终端的影响?终端一旦关闭则&的都将关闭(我做的实验都是这样,除非特殊的脚本能做成守护进程的方式)。主要现在网络上的帖子都是讲的fg,bg,jobs怎么用
,没有考虑到终端问题。"

1. source不开新进程,仅仅是在当前bash环境中执行另外一段bash代码,代码中的变量操作等对本环境有效。等同于.命令。
2. 本质上来说,以command &以后,这个进程就不在前台受控制了,比如你没法对它进行输入。终端关闭之所以导致&进程退出,是因为终端会在关闭时向进程发一个SIGHUP信号,进程对这个信号的默认处理方式是退出。应该也可以将终端设置成在关闭时不向进程发送SIGHUP信号,这样那些&进程就不会退出了。我的SecureCRT就不会有这种情况。
作者: wslmyb    时间: 2010-09-10 14:17
回复l.darkfire:
谢谢回答。不过对于你说的有一些问题。
“1. source不开新进程,仅仅是在当前bash环境中执行另外一段bash代码,”
请参看现象2中的sleep 104部分。
root      6209     1  0 11:01 ?        00:00:00 gnome-terminal //图形界面,父进程为1,没有问题
root      6290  6209  0 11:02 pts/4    00:00:00 bash //本身的pts/4,父进程为图形界面,没有问题
root      6388  6290  0 11:02 pts/4    00:00:00 bash //运行sleep 104命令的shell,父进程为6290
root      6426  6388  0 11:04 pts/4    00:00:00 sleep 104 //sleep 104命令,父进程shell为6388

按你的意思,6426(sleep 104命令)的父进程应该为pts/4,也就是6290.
可现在的情况是sleep命令它的父进程为6388.也就是pts/4(6290)又开了一个shell来执行sleep.
作者: l.darkfire    时间: 2010-09-10 14:21
root      6388  6290  0 11:02 pts/4    00:00:00 bash //运行sleep 104命令的shell,父进程为6290
这个是怎么来的
作者: wslmyb    时间: 2010-09-10 14:24
我就是不清楚这个是怎么来的 -_-!
作者: l.darkfire    时间: 2010-09-10 14:30
6290一定以某种方式fork了6388,比如( ... ),这个表达式会fork一个新的子bash,然后在子bash里执行括号里的命令,比如以下代码就可以产生上述情况:
#!/bin/bash
( sleep 104 )
作者: wslmyb    时间: 2010-09-10 14:35
回复l.darkfire:
对于你说的&后台的问题,我重新编辑了一下帖子。你能再帮我解释一下这个现象么,谢谢!
后台&问题:
现有脚本first.sh和second.sh
[root@localhost /]# cat /abc/first.sh
#!/bin/bash
. /abc/second.sh &
[root@localhost /]# cat /abc/second.sh
#!/bin/bash
while true
do
  sleep 500
done

现在执行
[root@localhost /]# source /abc/first.sh &
[1] 10458
[root@localhost /]# jobs
[1]+  Done                    source /abc/first.sh
[root@localhost /]#
ps auxf回车:
root     10386  0.0  1.6  81644 17388 ?        Sl   14:24   0:00 gnome-terminal
root     10391  0.0  0.0   2480   656 ?        S    14:24   0:00  \_ gnome-pty-h
root     10392  0.0  0.1   4912  1556 pts/1    Ss   14:24   0:00  \_ bash
root     10461  0.0  0.0   4608   920 pts/1    R+   14:27   0:00      \_ ps auxf
root     10390  0.0  0.0  12304   952 ?        S    14:24   0:00 scim-bridge
root     10459  0.0  0.0   4912   696 pts/1    S    14:27   0:00 bash
root     10460  0.0  0.0   3956   472 pts/1    S    14:27   0:00  \_ sleep 500
发现10459这个bash的父进程已经是根了。

然后退出这个终端,重新开一个终端
ps auxf回车:
root     10459  0.0  0.0   4912   696 ?        S    14:27   0:00 bash
root     10460  0.0  0.0   3956   472 ?        S    14:27   0:00  \_ sleep 500
root     10492  3.2  1.6  81528 17256 ?        Sl   14:28   0:00 gnome-terminal
root     10496  0.0  0.0   2480   656 ?        S    14:28   0:00  \_ gnome-pty-h
root     10497  0.3  0.1   4912  1496 pts/2    Ss   14:28   0:00  \_ bash
root     10518  0.0  0.0   4608   920 pts/2    R+   14:28   0:00      \_ ps auxf
root     10495  0.0  0.0  12304   952 ?        S    14:28   0:00 scim-bridge
发现10459这个进程还在。
有的人说&放在后台会受终端的影响,可是现在这个10459和10460进程都在,怎么解释?
作者: wslmyb    时间: 2010-09-10 14:38
回复6楼的说法:
对于这种说法,是不是我可以这样理解:当source command &。有后台&出现的情况,source也会出现fork的情况?
作者: l.darkfire    时间: 2010-09-10 14:38
在是正常的,说明你的终端在断开时没有发SIGHUP信号给进程。
说白了这是终端的特性,它在断开时,可以发SIGHUP信号也可以不发SIGHUP信号。和进程本身没有
什么关系。
作者: l.darkfire    时间: 2010-09-10 14:57
“对于这种说法,是不是我可以这样理解:当source command &。有后台&出现的情况,source也会出现fork的情况?”

首先source后面通常是跟一个脚本名,在当前环境下去执行脚本中的内容。
但是对于source script.sh &这种情况,bash会fork一个子进程去执行script,这是加了&后的不同之处。我也是刚才实验了一下才知道。
作者: wslmyb    时间: 2010-09-10 14:58
回复9楼:

那请看我后来补充的这个例子(first,second)。
这个终端如果在断开时,没有发SIGHUP信号。现在的现象是,10459的父进程为什么是1.这个进程10459是怎么来的?
[root@localhost /]# source /abc/first.sh &
[1] 10458
[root@localhost /]# jobs
[1]+  Done                    source /abc/first.sh
source first.sh进程是10458,就1句话,放在后台执行second.sh。所以马上jobs,看到已经Done。应该可以确定10459的父进程是10458.而10458是first而并非是本身的pts/1这个Shell(10392)。
之间的关系可以认为是这样
init->terminial->10392(pts/1)->10458(first)->10459(second)->10460(sleep)
因为10458瞬间执行完。而现在我不论是否退出终端,ps auxf和ps -ef看到10459的父进程都变为1了。这是怎么解释?为什么10459的父进程会变为1?
作者: l.darkfire    时间: 2010-09-10 15:04
因为当一个进程(10459)的父进程(1045死亡时,它的父进程就自动被系统设置为init(1)。
具体在父进程死亡的时候,把它的所有子进程的父进程设置为init(1)。
作者: l.darkfire    时间: 2010-09-10 15:04
因为当一个进程(10459)的父进程(10458 )死亡时,它的父进程就自动被系统设置为init(1)。
具体是在父进程死亡的时候,就把它的所有子进程的父进程设置为init(1)。
作者: wslmyb    时间: 2010-09-10 15:06
可是在没有退出终端的时候,10459的父进程应该是10392啊.因为没有退出终端呢。刚执行完source first & 后执行ps看结果,看到的10459的父进程也为1了。
而且现在这些都是用source执行的,居然都是父子进程的关系,就是你刚才说的source script &的方式会fork一个shell。所以我最开始对这事很不明白。
作者: l.darkfire    时间: 2010-09-10 15:09
1. source script不会fork子bash来执行。
2. source script &会fork子bash来执行。
3. 父进程A死亡后,它的子进程B的父进程全被设置为1,而不是被设置为父进程A的父进程C。
作者: wslmyb    时间: 2010-09-10 15:14
哦,好的。非常感谢!
作者: wslmyb    时间: 2010-09-10 15:15
CU的高手就是多啊,这个事纠结了我1天了。
作者: l.darkfire    时间: 2010-09-10 15:16
互相学习呗
作者: wslmyb    时间: 2010-09-10 15:24
还有1个问题。
init->terminial->10392(pts/1)->10458(first)->10459(second)->10460(sleep)
在10458瞬间执行完退出的时候,为什么没有给10459发SIGHUP信号呢。如果发了,10459就应该结束的。
作者: l.darkfire    时间: 2010-09-10 15:27
自己死亡便向子进程发送SIGHUP的特性是终端才有的,程序自己默认并不会做这个事情,除非你自己编写一个程序这样做。
作者: wslmyb    时间: 2010-09-10 15:31
哦,原来是这样!l.darkfire兄你太N了。
作者: l.darkfire    时间: 2010-09-10 15:47
N的都躲在旁边看呢
作者: chinesedragon    时间: 2010-09-13 11:52
看看!!!!!!




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2