█ SKEMA ★ ESC高商名校 █
█ 公立大学直入项目申请 █
IFAA艺术设计/时尚奢侈品/计算机/
营销管理等,BAC+1至+9热招
★☆Cafa-Formations☆★
法国波尔多专业品酒师学院
★IESIG FLE★ 十五年教学经验
巴黎性价比最高的法语学校
顶级高商 公立大学 艺术院校
2018年春季入学现已开始招生
WELLER高商,中国认证本硕招生
红酒/奢侈品/旅游/市场传媒/金融
█ A.A.A.国际语言中心 █
法语学校◆法国签证◆法国实习
2017秋季入学火热申请中!!!
顶级高商★时尚艺术★工程师
UFEC国际商贸学院-成功之门
FLE/Prépa/Bac+1 - Bac+9
EEEA博士教育
PhD-DBA-MBA, bac+4至bac+9
2018春季入学申请进行时
艺术院校 公立大学 顶级高商
★排名高商ISC,学历认证★
★本硕连读MBA项目18个月★
❖ISMAC❖性价比最高的私校
★更多免费服务等你来拿★
★★★CAMPUS LANGUES★★★
法语/英语/备考/国际班级
巴黎工程师ESILV官方直录
巴黎高商EMLV文凭中国认证
SOFRA 索法 ★ 留法院校咨询
顶级工程师/TOP高商/优质大学
❖IBSM❖法国高等商学院
红酒旅游/视觉传达/服装设计
●★ IPLME----亿搏商学院★●
顶级高商|文凭认证|公立直录
█公立大学专业申请█
ICD认证高等商学院巴黎图卢兹
★★★ INSEEC高等商学院 ★★★
官方直录◆文凭认证◆优质教学
查看: 2238|回复: 1
打印 上一主题 下一主题

如何获得expect中spawn进程的返回值

[复制链接]
新浪微博达人勋
跳转到指定楼层
楼主
发表于 2017-3-6 10:33:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
回复
  
      报警器参考:人体静电释放报警器  
    一、返回值校验
    返回值校验始终是一个安全可靠软件或者说软件或者说作业的基本流程,无论执行什么工作,都应该告诉使用者这个子进程执行的结果如何,就是通常所说的,你倒是吱一声? 6杂趀xpect来说,它的情况是比较特殊的,它执行ssh执行远程进程的时候,我们在expect中读取的只能是ssh的返回值,而不是通过ssh执行的命令的返回值。
    如果要获得ssh执行的远端进程的返回值,这个是用通用的方法就可以了。例如我们执行了一个scp命令,执行之后可以在命令提示符的正则表达式中做特殊处理,方法就是添加一些变量表示是第几次出现命令提示符命令,之后更具次数来执行shell的内置变量 $? 获得刚刚执行的子进程的返回值,再通过senduser或者其它的脚本变量将这个返回值保存起来,在进程退出的时候将这个值返回给执行者。
    现在考虑一下对于一个本地进程的返回值如何获得。执行本地命令并不是一个稀缺的现象,例如我们在本地执行ync命令,此时我们希望得到的其实就是这个ync的返回值。
    二、网络上的解决方法
    网络上常见的说法就是通过
    catch wait result
    这里的catch并不是expect的命令,而是expect的基础上建立的tcl库中的一个函数,所以在expect的代码中找不到该命令的实现。说到这里,我们可以看到tcl的设计思想对于命令的影响。通常的脚本例如bash,设置一个变量是通过 var=val的方式来定义一个变量的值,而tcl中则是通过 set var val来实现,这和tcl中提出的所有内容都是命令一致的。bash中对于变量赋值的语法其实是通过专门的解析方法来实现的,它会在每个命令中搜索是否存在有等号的存在。假设如果是通过set,这就是一个普通的命令,它有两个参数,这样词法分析也简单一些。简单的原因不是在于不能实现复杂的功能,而是因为简单的东西具有更强的扩展性和更好的可维护性,这些对于软件的维护来说都是非常有价值的属性。
    wait是expect的内置命令,所以可以看一下这个命令对应的函数实现:
    argv++;
    argc--;
    for (;argc>0;argc--,argv++) {
    if (streq(*argv,"-i")) {通过-i可以指定等待那个子进程的返回,因为expect同样是可以同时spawn多个子进程的,所以这个-i是有意义的。
    argc--; argv++;
    if (argc==0) {
    exp_error(interp,"usage: -i spawn_id");
    return(TCL_ERROR);
    }
    chanName = *argv;
    } else if (streq(*argv,"-nowait")) {
    nowait = TRUE;
    }
    }
    if (!chanName) {
    if (!(esPtr = expStateCurrent(interp,0,0,1))) return TCL_ERROR;
    } else {
    if (!(esPtr = expStateFromChannelName(interp,chanName,0,0,1,"wait")))
    return TCL_ERROR;
    }
    ……
    if (result == -1) {
    sprintf(interp->result,"%d %s -1 %d POSIX %s %s",
    esPtr->pid,spawn_id,errno,Tcl_ErrnoId(),Tcl_ErrnoMsg(errno));
    result = TCL_OK;
    } else if (result == NO_CHILD) {
    exp_error(interp,"no children");
    return TCL_ERROR;
    } else {
    sprintf(interp->result,"%d %s 0 %d",
    esPtr->pid,spawn_id,WEXITSTATUS(esPtr->wait));
    也就是说,wait命令的返回值是一个"%d %s 0 %d"格式的字符串,所以我们可以通过
    set result wait
    来说的子进程的返回值,如果通过wait没有指定等待的接口,默认是当前spawn的进程编号。而结果的第四个字段就是通过waitpid获得子进程的返回值。
    三、如果没有执行wait
    这里可以看到,如果没有执行wait,expect是始终不会执行waitpid,这样多次执行spawn之后派生的所有子进程在expect退出之前都是处于Zombie状态。
    四、一个例子
    spawn echo we have echoed
    expect eof
    spawn echo we echoed again
    set result [ wait result]
    puts $result
    sleep 12345
    输出
    spawn echo we have echoed
    we have echoed
    spawn echo we echoed again
    2907 exp5 0 0
    此时有兴趣的同学可以通过 ps aux | grep echo
    看一下,系统中会有一个Zombie状态的进程,如果去掉之前的wait作,系统中会有两个Zombie的echo进程。
新浪微博达人勋
席梦思
发表于 2017-3-8 16:39:43 | 只看该作者
你是那这里当笔记本么,版主呢。。。
回复 支持 反对 使用道具 举报
您需要登录后才可以回帖 登录 | 注册 新浪微博登陆
本版积分规则
关于我们| 服务条款| 联系我们| 广告服务| 复制新欧洲| 欧团网| 游游旅行| Cookies| ( 沪ICP备15032081号 )   
© 2002-2017 E.CAN Inc.
快速回复
返回列表
便民工具
投诉建议
APP下载
微博分享
微信分享
寻伴同驴
返回顶部