首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在proc内运行proc时预期失败

在proc内运行proc时预期失败
EN

Stack Overflow用户
提问于 2015-05-29 14:44:12
回答 2查看 1.7K关注 0票数 4

我的脚本在使用一个proc时运行良好(检索sftp提示符)。但是当我试图在proc中使用proc时,脚本会被卡住,我不知道为什么。

请不要重构代码,这不是重点,我需要了解的问题是什么。

工作代码:

代码语言:javascript
复制
proc sftp_connect {} {
  set times 0;
  set connection_retry 2
  set timeout 1;
  while { $times < $connection_retry } {
    spawn sftp ${SFTP_USER}@${SFTP_SERVER}
    expect {
      timeout { puts "Connection timeout"; exit 1}
      default {exit 2}
      "*assword:*" { 
        send "${SFTP_PASSWORD}\n";
        expect {
          "sftp>" { puts "Connected"; set times [ expr $times+1]; exp_continue}
        }
      }
    }
  }
  send "quit\r";
}

sftp_connect

调试输出:

代码语言:javascript
复制
expect: does "\r\nsftp> " (spawn_id exp5) match glob pattern "sftp>"? yes

但是在将发送密码移动到单独的proc后,expect不再检索sftp提示符("sftp>"):

代码语言:javascript
复制
proc sftp_send_password {} {
  send "${SFTP_PASSWORD}\n";
  expect {
    "sftp>" { puts "Connected"; set times [ expr $times+1]; exp_continue}
  }
}

proc sftp_connect {} {
  set times 0;
  set connection_retry 2
  set timeout 1;
  while { $times < $connection_retry } {
    spawn sftp ${SFTP_USER}@${SFTP_SERVER}
    expect {
      timeout { puts "Connection timeout"; exit 1}
      default {exit 2}
      "*assword:*" { sftp_send_password }
    }
  }
  send "quit\r";
}

sftp_connect

调试输出:

代码语言:javascript
复制
expect: does "" (spawn_id exp0) match glob pattern "sftp>"? yes
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-29 15:56:33

我手头没有“探索期待”的副本,但我认为您遇到了一个可变范围问题。spawn无形地设置了一个名为spawn_id的变量。当您在proc中调用派生时,该变量的作用域仅为该proc。宣布它是全球性的:

代码语言:javascript
复制
proc sftp_connect {} {
  global spawn_id
  # ... rest is the same
}

我认为您不必在sftp_send_password中做同样的事情,因为expect有一个比Tcl更宽容的范围界定方案(如果expect找不到局部变量,请查看全局命名空间)。

但是,由于相同的变量范围问题,sftp_send_password proc不会影响sftp_connect中的times变量。我建议你

代码语言:javascript
复制
proc sftp_send_password {times_var} {
  upvar 1 $times_var times     ;# link this var to that in the caller
  send "${SFTP_PASSWORD}\n";
  expect {
    "sftp>" { puts "Connected"; incr times; exp_continue} 
  }
  # note use of `incr` instead of `expr`
}

然后sftp_connect proc发送times变量名称

代码语言:javascript
复制
sftp_send_password times
票数 5
EN

Stack Overflow用户

发布于 2015-05-30 15:33:14

以下内容来自expect的手册页:

Expect对范围界定采取了相当宽松的观点。特别是,通过特定于Expect程序的命令读取的变量将首先从本地范围中查找,如果找不到,则在全局范围中查找。例如,这避免了在您编写的每个使用expect的过程中放置global timeout的需要。另一方面,编写的变量总是在本地作用域中(除非发出了global命令)。这导致的最常见的问题是当在过程中执行spawn 时。在过程之外的spawn_id不再存在,因此生成的进程不再可以仅仅因为作用域的限制而访问。在这样的过程中添加一个global spawn_id

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30532532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档