unix 在进程内运行进程时expect失败

7eumitmz  于 2023-05-06  发布在  Unix
关注(0)|答案(2)|浏览(207)

我的脚本工作正常(检索sftp提示)时,使用一个proc。但是当我尝试在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

但是在将send password移动到单独的proc之后,expect不再检索sftp提示符(“sftp〉”):

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
ufj5ltwl

ufj5ltwl1#

我手头上没有“Exploring Expect”,但我认为您遇到了一个变量作用域问题。spawn设置了一个名为spawn_id的变量。当你在一个proc中调用spawn时,这个变量的作用域只针对这个proc。将其声明为全局:

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

我认为您不必在sftp_send_password中做同样的事情,因为expect的作用域方案比Tcl更宽松(如果expect找不到局部变量,请查看全局名称空间)。
由于相同的变量范围问题,sftp_send_password proc不会影响sftp_connect中的times变量。我建议

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变量name

sftp_send_password times
pgccezyw

pgccezyw2#

以下是来自expectman page
Expect对作用域的定义有一个相当开放的观点。特别是,由特定于Expect程序的命令读取的变量将首先从局部范围中查找,如果找不到,则在全局范围中查找。例如,这样就不需要在您编写的每个使用expect的过程中放置global timeout。另一方面,写入的变量总是在局部作用域中(除非发出了global命令)。**最常见的问题是当spawn在过程中执行时。**在过程之外,spawn_id不再存在,因此由于作用域的原因,派生的进程不再可访问。在这样的过程中添加一个global spawn_id

相关问题