在proc

时间:2015-05-29 14:44:13

标签: bash unix tcl expect

使用一个proc时,我的脚本运行正常(检索sftp提示符)。但是当我尝试在proc内部使用proc时,脚本会卡住,我不知道为什么。

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

工作代码:

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

调试输出:

expect: does "\r\nsftp> " (spawn_id exp5) match glob pattern "sftp>"? yes

但是在将发送密码移动到单独的proc之后,期望不再检索sftp提示符(“sftp&gt;”):

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

调试输出:

expect: does "" (spawn_id exp0) match glob pattern "sftp>"? yes

2 个答案:

答案 0 :(得分:2)

我没有方便的“探索期待”副本,但我认为你正在遇到一个变量范围问题。 spawn无形地设置名为spawn_id的变量。在proc中调用spawn时,该变量的范围仅限于该proc。将其声明为全局:

proc sftp_connect {} {
  global spawn_id
  # ... rest is the same
}

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

由于相同的变量范围问题,您的sftp_send_password proc不会影响times中的sftp_connect变量。我推荐

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变量名称

sftp_send_password times

答案 1 :(得分:1)

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

  

Expect对范围界定采取相当自由的观点。特别是,将首先从特定于Expect程序的命令读取的变量          本地范围,如果没有找到,则在全局范围内。例如,这消除了在您编写的每个过程中放置​​global timeout的需要          使用期望。另一方面,写入的变量始终在本地范围内(除非已发出global命令)。 最常见的          这个问题导致的是在程序中执行spawn在程序之外,spawn_id不再存在,因此产生的进程不再存在          因为范围界定而无法访问。在此类程序中添加global spawn_id