免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 934 | 回复: 0
打印 上一主题 下一主题

怎么理解shell执行命令时是启用了一个新shell [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-16 23:51 |只看该作者 |倒序浏览

怎么理解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 ...


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/98498/showart_1966570.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP