文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>怎么理解shell执行命令时是启用了一个新shell

怎么理解shell执行命令时是启用了一个新shell

时间:2009-06-16  来源:hbkh2000

怎么理解shell执行命令时是启用了一个新shell?


DBNAME是在profile里定义的环境变量并被export
所以
echo $DBNAME
sbss

但是
$a=1
而不扩展
那么
echo $a
1
为什么这个a变量被传到子shell了呢

【发表回复】【查看论坛原帖】【添加到收藏夹】【关闭】
 ivhb 回复于:2004-09-10 13:00:23
[code:1:580cfa5115]
要设计一个测试案例是不容易的。现在还没有想好。
不过可以给你一点参考

a=b

首先 type echo 应该是 built-in,当然是在当前的shell运行的。不会启动子shell。所以没有传递的意思。

which echo,应该有/usr/bin/echo

好的,现在开始
/usr/bin/echo $a

这一定会启动一个子shell来运行的。但是要注意,当前shell启动shell前,已经做了$a的展开,(set -x看看?)。也就是说,实际传入的命令行为
/usr/bin/echo b
因此,你看到的还是b,已经被当前shell解析$a后的展开式。但是你由此
作出a也就子shell继承的推断是有问题的
[/code:1:580cfa5115]

 ivhb 回复于:2004-09-10 14:45:50
[code:1:acba6be62d]
不知道这样的测试,在您的系统是什么结果
set -x            为了能看到您的实际输入

export   var="hello"
avar=" world"
echo "$var" "$avar"
/bin/echo "$var" "$avar"
echo '$var' '$avar'
/bin/echo '$var' '$avar'
eval echo '$var' '$avar'
eval /bin/echo '$var' '$avar'
sh eval echo '$var' '$avar'
sh eval /bin/echo '$var' '$avar'

[/code:1:acba6be62d]

 compnik 回复于:2004-09-10 14:48:09
[quote:b336f4dc28="ivhb"]
好的,现在开始
/usr/bin/echo $a

这一定会启动一个子shell来运行的。[/quote:b336f4dc28]
[code:1:b336f4dc28]
[x@as bin]# file echo
echo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
[/code:1:b336f4dc28]
是个shell script 时 ,是在subshell中执行的,
echo 是一个二进制的执行文件,怎么会在子shell中执行呢? 这个echo 还是在当前shell中执行阿

 ivhb 回复于:2004-09-10 18:26:54
[code:1:b06e468b5d]
就我所知,执行一个二进制文件,一定是exec()来执行的。
如果是当前进程,exec()执行完该二进制文件后,还能继续运行当前shell么?
[/code:1:b06e468b5d]

 compnik 回复于:2004-09-10 19:04:52
执行完二进制文件是产生个该二进制文件(程序)的新进程,但不是一个shell进程, 所谓在subshell中执行只不过是由subshell产生该程序的进程, 而不是当前shell产生

 ivhb 回复于:2004-09-10 19:49:37
[code]
当前的shell,如果fork了,那么fork之后,有一份当前shell的完整的copy,这个copy,就认为是子shell,然后子shell就execlp指定的文件。
如果当前shell没有fork,就是当前shell中执行。

执行二进制文件里,不fork,exec,那么该二进制文件执行完后,一定是
中止了当前的运行环境。这点应该可以确认的吧。由此我想
我和你的分歧在于,可能是因为父进程fork了,其子进程和本身一样。所以不能成为子shell??

当前shell一旦fork,能说,fork的进程不是shell?只是fork到exec的动作太快,fork出来的子shell的进程空间立马被该二进制文件覆盖。

这是我的理解,还望斧正
[code]

 pinecrane 回复于:2004-09-10 20:23:14
谢谢楼上的两位大侠:我明白了。
关键在于:shell 进程与普通的命令进程(也算是shell的子进程,单不是子shell进程,两者的区别就是子shell进程会拥有父shell进程的环境变量的副本,而普通的进程没有,普通的进程就相当于一词函数调用,把我们需要用到的环境变量等传递进去,然后进行操作,很有可能会修改变量的值.)

在命令行执行某个命令时,由primary shell fork 一个普通的进程,并传递需要的变量(可能时常量,比如一个字符串,也可能时一个已经定义了的变量,如环境变量)。但是执行环境并没有改变,普通命令进程通primary的一个共同之处就是:共享标准输入,标准输出等文件。所以尽管在命令进程里进行屏幕打印等操作我们也能看到)。
而在script中执行时,则由primary shell fork 一个sub shell(大概就是primary shell 的copy),所以该sub shell 拥有primary shell 里定义的所有环境变量,只不过是副本了,所以对环境变量的修改不会影响到父shell 进程。

所以 :
$echo $a
实际就是在当前shell环境那执行一个普通命令调用。
$unset a
把a的地址传递给unset命令,在unset命令里清除。这与:
$a=""有类似的功效而已。

综上,所谓shell: 1.充当主进程的角色。
                          2.在其生命期内(没有exit或者log out).维护一些必要的环境变量,供普通命令进程或者sub shell使用。
以上是我的理解,不对的地方请指出。!!
谢谢!!

 compnik 回复于:2004-09-10 20:41:44
[quote:a3b603f6a9="ivhb"]当前shell一旦fork,能说,fork的进程不是shell?只是fork到exec的动作太快,fork出来的子shell的进程空间立马被该二进制文件覆盖。
[/quote:a3b603f6a9]
当前shell直接就fork 出一个二进制文件的进程, 就不用先fork个subshell再exec了,那是浪费资源
pinecrane说的是正确的

 網中人 回复于:2004-09-11 01:09:21
[quote:acb778ccaa="compnik"]当前shell直接就fork 出一个二进制文件的进程, 就不用先fork个subshell再exec了,那是浪费资源 [/quote:acb778ccaa]
這個我也不確定, 但從眾多文件的說明上, 似乎大都說是先 fork 再 exec 再 exit 的...

a=b
/bin/echo $a
理解上, a 是一個 local var, 不會被帶進 child env 中的.
但為何可以看到呢?
嗯... 看過 shell 十三問的朋友, 一定記得我最少強調過兩次如下的觀念了:
---> 在 command line 中的變數替換完成後, 會重組命令行!

因此, /bin/echo $a 在完成替換後, 會被重組為 /bin/echo b , 
然後才 fork & exec ...
相关阅读 更多 +
排行榜 更多 +
神龙崛起之战

神龙崛起之战

冒险解谜 下载
合金击车

合金击车

冒险解谜 下载
隐藏旅途2逃脱冒险

隐藏旅途2逃脱冒险

冒险解谜 下载