免费注册 查看新帖 |

Chinaunix

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

[文本处理] 理解进程概念的来帮忙看看:/bin/echo 为什么可以显示出shell的局部变量,也就是非ex [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-11-17 21:07 |只看该作者 |倒序浏览
我一共有两个问题,都是关于进程 与 变量的。

第一个进程的问题:builtin echo vs /bin/echo
linux下面有两个echo,一个是builtin,还有一个是外部命令/bin/echo
不同的就是builtin 的echo 命令执行的时候,不会产生一个新的进程,而是在当前shell进程执行,而/bin/echo 执行的时候,会产生一个新的进程。
当一个shell进程fork 出一个进程的时候,子进程只会继承父进程使用export命令设置的变量——当然这些变量内部的实现是通过setenv()函数来实现的。——相对的,shell的一些其他非export设置的变量,子进程是无法继承的。
所以假如当前在第一个shell进程下,使用name=value的形式设置了一些变量,但是这些变量并没有使用export 为可继承的变量,则执行bash时,这些变量时无法被子进程继承的。就像下面这样,使用parent# 和 child# 提示字符串区别父进程与子进程。

parent# name=Tom
parent# echo $name
Tom
parent# bash   (这条命令会产生一个子进程)
child# echo $name (在子进程中查看变量name)

child#

以上都是合理的。

但是现在看另一种情况。假如父进程使用 name=Jack 设置了一个叫做name的变量,那么这个变量时不可以被子进程继承的,而使用/bin/echo 这个可执行文件,会产生一个子进程,但是这个子进程竟然可以打印出name的值来。实在是不明白为什么。

parent# name=Jack
parent# echo $name (echo 内置命令,就属于本进程,可以看到本进程的变量肯定是没问题的)
Jack
child# /bin/echo $name (使用/bin/echo 外部可执行文件,产生一个子进程,答应 变量$name的值)
Jack


发现子进程竟然也可以看到变量的值,实在想不明白了。


第二个问题是关于find命令的问题:
使用find命令查找出文件时,假如想对查找出的文件进行操作,则使用-exec操作
例如:
find / -name *.txt -exec ls -l {}  \;  (这个命令查找出文件系统中所有的脚本文件,并且使用ls -l 命令列出文件详细信息)

不明白的是,为什么使用-exec 操作后,最后使用一个 \; ,是将分号用反斜杠转义吗?意义何在?


Thanks in advance!


论坛徽章:
39
辰龙
日期:2013-08-21 15:45:192015亚冠之广州富力
日期:2015-05-12 16:34:52亥猪
日期:2015-03-03 17:22:00申猴
日期:2015-03-03 17:21:37未羊
日期:2014-10-10 13:45:41戌狗
日期:2014-06-17 09:53:29巨蟹座
日期:2014-06-12 23:17:17双鱼座
日期:2014-06-10 12:42:44寅虎
日期:2014-06-09 12:52:172015亚冠之卡尔希纳萨夫
日期:2015-05-24 15:24:35黄金圣斗士
日期:2015-12-02 17:25:0815-16赛季CBA联赛之吉林
日期:2017-06-24 16:43:52
2 [报告]
发表于 2013-11-17 21:32 |只看该作者
本帖最后由 关阴月飞 于 2013-11-17 21:33 编辑

回复 1# 呼呼的id

第一个问题: 外部命令 /bin/echo $name 的时候为什么能打出变量$name的值:
个人认为:
这里的 $name 是作为传参传给 /bin/echo的, 在/bin/echo 执行之前,$name 就已经被当前shell 进行了变量替换操作,所以真正执行的命令应该是:
/bin/echo  Jack  #$name 的值


第二个问题是关于find命令的问题:
find / -name *.txt -exec ls -l {}  \;

;号在shell里面是一个元字符,表示命令的终结  \; 就是为了转义,不让shell 把;给预处理了。

论坛徽章:
29
程序设计版块每日发帖之星
日期:2016-02-29 06:20:0015-16赛季CBA联赛之天津
日期:2016-08-10 10:33:1115-16赛季CBA联赛之深圳
日期:2016-08-17 15:07:2015-16赛季CBA联赛之佛山
日期:2016-11-07 11:33:5015-16赛季CBA联赛之广夏
日期:2016-11-15 09:13:31CU十四周年纪念徽章
日期:2016-11-24 14:12:25极客徽章
日期:2016-12-07 14:03:4015-16赛季CBA联赛之深圳
日期:2016-12-07 17:15:2715-16赛季CBA联赛之北京
日期:2016-12-22 09:30:0115-16赛季CBA联赛之深圳
日期:2016-12-22 10:49:2115-16赛季CBA联赛之山西
日期:2017-02-10 09:05:3215-16赛季CBA联赛之同曦
日期:2017-02-27 14:19:08
3 [报告]
发表于 2013-11-17 22:10 |只看该作者
细节问题又加强很多了, 多谢

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
4 [报告]
发表于 2013-11-18 10:51 |只看该作者
原因见2楼

另外
"当一个shell进程fork 出一个进程的时候,子进程只会继承父进程使用export命令设置的变量"
这个描述是错误的

论坛徽章:
0
5 [报告]
发表于 2013-11-18 12:58 |只看该作者

回复 2# 关阴月飞

第一个变量那个问题:总觉得怪怪的:因为/bin/echo 只是一个外部可执行文件,是可执行文件的话,shell不应该随便去改变传给这个可执行文件的参数。
假如我用c语言编写了一个程序,编译为一个可执行程序。本来我的程序里面对于传给main函数的参数都是可预料的。
但是shell 父进程在看到传给我的程序的参数的时候,私自就给我做了改变,这一下子就乱套了。
除非/bin/echo 已经是一个标准了,是大家公认的,商量好了,传给echo的参数,shell会先做替换。那么shell改了传给它的参数可以。
或者说shell的作者和/bin/echo 的作者是同一个人,他想怎么改变传给/bin/echo 的参数 都是可以的了。

find 的那个我还是不明白:
加 \; 肯定是转义了,但总觉得多此一举了。
因为命令设计成这样
find / -name *.txt -exec ls -l {}
我觉得也可以啊,难道这样的话,会让计算机某些地方产生歧义吗?


   

论坛徽章:
0
6 [报告]
发表于 2013-11-18 13:05 |只看该作者
回复 4# waker


哦?哪里错误了,可以继承的变量肯定归根结底都是底层使用了 c语言 setenv() 函数设置的变量。
而export的内置命令,肯定是用到了setenv() 函数的。
对了declare -x name=value,设置的变量也是可以被子进程继承的。
但是declare 命令的 -x 参数其实就是想表示 export的意思。并且执行declare -x 这个带-x 参数的命令的时候,底层上肯定也是调用了 setenv()函数。

还有其他的使用命令将变量 ——>设置为可以被子进程继承的变量的方法吗

论坛徽章:
39
辰龙
日期:2013-08-21 15:45:192015亚冠之广州富力
日期:2015-05-12 16:34:52亥猪
日期:2015-03-03 17:22:00申猴
日期:2015-03-03 17:21:37未羊
日期:2014-10-10 13:45:41戌狗
日期:2014-06-17 09:53:29巨蟹座
日期:2014-06-12 23:17:17双鱼座
日期:2014-06-10 12:42:44寅虎
日期:2014-06-09 12:52:172015亚冠之卡尔希纳萨夫
日期:2015-05-24 15:24:35黄金圣斗士
日期:2015-12-02 17:25:0815-16赛季CBA联赛之吉林
日期:2017-06-24 16:43:52
7 [报告]
发表于 2013-11-18 13:37 |只看该作者
本帖最后由 关阴月飞 于 2013-11-18 13:39 编辑

回复 5# 呼呼的id


    你把整个命令当成一条命令行来看, 命令执行之前shell都会对其 按照相关规则进行重组,重组后才开始执行,这里面主要是个“输入命令==》执行命令“的过程,和传参没多大关系,别自己给自己挖坑下套了。

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
8 [报告]
发表于 2013-11-18 15:26 |只看该作者
本帖最后由 waker 于 2013-11-18 15:27 编辑

回复 6# 呼呼的id

直接上代码

  1. unset var
  2. var=xxoo
  3. ( pstree -p $$
  4.   echo -n "pid is "
  5.   cd /proc/self/task
  6.   echo -n *
  7.   echo " var=$var"
  8. )
  9. echo pid is $$ var=$var
复制代码
俺相信fork之后两个进程中的变量是一致的,之后再怎么处理变量是进程自己的事,想保留就保留,想清除就除
   

   

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
9 [报告]
发表于 2013-11-18 15:29 |只看该作者
当然关于你一楼问的问题,原因就是关阴月飞的论述,echo 根本没看到什么变量,它得到一个命令行参数而已

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
10 [报告]
发表于 2013-11-18 15:38 |只看该作者
关于find的\;, find看到的就是;,要用它来结束 -exec 后续的参数,表示这一个-exec到这时为止了,后面你还可以-ls 啊或继续来一个-exec xx oo ;
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP