如何搜索存储在列表中的多个模式,直到找到所有项目或已经过了一定时间

The*_*ter 5 tcl expect

我正在创建一个简单的expect脚本,它将监视tcpdump的输出以获取多播地址列表.我想知道在预期超时之前是否从列表中的每个多播地址接收到数据包.

我有一个有效的解决方案,但它效率低下,我相信我没有充分利用expect和tcl的全部功能.无论如何这里是我目前的脚本:

set multicast_list {225.0.0.1 225.0.0.2 225.0.0.3}

send "tcpdump -i ixp1\r"
# If tcpdump does not start, unzip it and run it again
expect {
  "tcpdump: listening on ixp1" {}
  "sh: tcpdump: not found" {
    send "gunzip /usr/sbin/tcpdump.gz\r"
    expect "# "
    send "tcpdump -i ixp1\r"
    exp_continue
  }
}
# Set timeout to the number of seconds expect will check for ip addresses
set timeout 30
set found [list]
set not_found [list]
foreach ip $multicast_list {
  expect {
    "> $ip" { lappend found "$ip" }
    timeout { lappend not_found "$ip" }
  }
}
set timeout 5
# Send ^c to stop tcpdump
send -- "\003"
expect "# "
Run Code Online (Sandbox Code Playgroud)

因此,您可以看到脚本将一次查找一个IP地址,如果看到ip,它会将其添加到找到的地址列表中.如果期望超时,它会将地址添加到not_found列表并搜索下一个地址.

现在回到我的问题:是否有一种方法可以在给定的时间内同时监视所有IP地址的tcpdump.如果要找到地址,我想将它添加到找到的地址列表中,理想情况下停止期待它(这可能不可能,我不确定).关键是我需要脚本来并行监视列表中的所有IP.我不能对每个地址进行硬编码,因为它们每次都会有所不同,我要查找的地址数量也会有所不同.我真的可以使用一些期待大师的帮助.

谢谢!

The*_*ter 0

这是我完成的脚本。它使用 Donal 解决方案中的相同代码,但我添加了一些检查来修复一些未考虑到的问题。

set multicast_list {225.0.0.1 225.0.0.2 225.0.0.3}
set tcpdump_timeout 10

spawn /bin/bash
expect "] "

# Create the runtime-generated expbody to use later
# Generate the timeout clause as a normal literal
set expbody {
timeout {
    set not_found [array names waiting]
    unset waiting
}
}
foreach ip $multicast_list {
    set waiting($ip) "dummy"
    # Generate the per-ip clause as a multi-line string; beware a few backslashes
    append expbody "\"> $ip\" {
    set currentTime \[clock seconds\]
    if { \$currentTime < \$endTime } {
      if { \[ info exists waiting($ip) \] } {
        lappend found $ip
        unset waiting($ip)
      }
      if {\[array size waiting\]} exp_continue
    }
}\n"
}

# Set expect timeout and create empty lists for tcpdump results
set timeout $tcpdump_timeout
set found [list]
set not_found [list]

# Start tcpdump
send "tcpdump -i ixp1\r"
expect "tcpdump: listening on ixp1"

# Get the time to stop tcpdump
set endTime [ expr [clock seconds] + $tcpdump_timeout ]

# Feed expbody into expect; it's none-the-wiser that it was runtime-generated
expect $expbody
set not_found [array names waiting]
unset waiting
# Send ^c to stop tcpdump
send -- "\003"
expect "# "
Run Code Online (Sandbox Code Playgroud)