Search code examples
bashtclexpectspawn

TCL/Expect - How to spawn bash and control it OR why expect clausule does not see send clausule results


How can I control bash with Expect? My Expect script looks like this:

#!/usr/bin/expect

# ENABLE DEBUGGING
exp_internal 1


set timeout 10
log_user 0

spawn bash -i
sleep 5
send "ls -1 db*\r"
expect {
  -re "^db.*$" {
    puts $expect_out(0,string)
  }

  timeout {
    send_error "Script has reached the 'timeout' branch\n"
  } 
}

But I always get this output which is caused by time out:

parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {4740}
send: sending "ls -1 db*\r" to { exp4 }
Gate keeper glob pattern for '^db.*$' is 'db*'. Activating booster.

expect: does "" (spawn_id exp4) match regular expression "^db.*$"? Gate "db*"? gate=no

expect: does "Agent pid 6228\r\nIdentity added: /home/wakatana/.ssh/id_rsa (/home/wakatana/.ssh/id_rsa)\r\n\u001b[?1034h\u001b]0;~/scripts\u0007\r\r\n\u001b[32mwakatana@ANTARES \u001b[33m~/scripts\u001b[0m\r\r\n$ ls -1 db*\r\n" (spawn_id exp4) match regular expression "^db.*$"? Gate "db*"? gate=yes re=no

expect: does "Agent pid 6228\r\nIdentity added: /home/wakatana/.ssh/id_rsa (/home/wakatana/.ssh/id_rsa)\r\n\u001b[?1034h\u001b]0;~/scripts\u0007\r\r\n\u001b[32mwakatana@ANTARES \u001b[33m~/scripts\u001b[0m\r\r\n$ ls -1 db*\r\ndbupgrade.log\r\n" (spawn_id exp4) match regular expression "^db.*$"? Gate "db*"? gate=yes re=no

expect: does "Agent pid 6228\r\nIdentity added: /home/wakatana/.ssh/id_rsa (/home/wakatana/.ssh/id_rsa)\r\n\u001b[?1034h\u001b]0;~/scripts\u0007\r\r\n\u001b[32mwakatana@ANTARES \u001b[33m~/scripts\u001b[0m\r\r\n$ ls -1 db*\r\ndbupgrade.log\r\n\u001b]0;~/scripts\u0007\r\r\n\u001b[32mwakatana@ANTARES \u001b[33m~/scripts\u001b[0m\r\r\n$ " (spawn_id exp4) match regular expression "^db.*$"? Gate "db*"? gate=yes re=no
expect: timed out
Script has reached the 'timeout' branch

File that I am trying to ls exists:

$ ls -1 db*
dbupgrade.log

PS: This was inspired by this question


Solution

  • In Expect, the ^ and $ mean very differently:

    Note that in many editors, the ^ and $ match the beginning and end of lines respectively. However, because expect is not line oriented, these characters match the beginning and end of the data (as opposed to lines) currently in the expect matching buffer.

    You can do like this:

    [STEP 101] # cat foo.exp
    spawn bash --noprofile --norc
    sleep 1
    send "ls -1 db*\r"
    expect {
        -re {[\r\n]+(db.*?)[\r\n]+} {
            send_user "\n>>> $expect_out(1,string) <<<\n"
        }
    }
    [STEP 102] # ls -1 dbupgrade.log
    dbupgrade.log
    [STEP 103] # expect foo.exp
    spawn bash --noprofile --norc
    bash-4.3# ls -1 db*
    dbupgrade.log
    
    >>> dbupgrade.log <<<
    [STEP 104] #