Search code examples
expect

In expect, how can I interact with multiple spawned processes?


I do need to run multiple (concurrently) and interact with both of them. Is there a way to do that? Some searching used exp_background but that command was not found when I tried it.

What I tried

I wrote three scripts, an expect script ex1.ex, and two shell scripts t1.sh and t2.sh. They are listed below:

# File ex1.ex
#!/usr/bin/expect
puts "starting 1\n"
spawn ./t1.sh
set pid1 $spawn_id
puts "spawn_id is $spawn_id, pid1 is $pid1"
expect_background $pid1

puts "starting 2\n"
spawn ./t2.sh
set pid2 $spawn_id
puts "spawn_id is $spawn_id, pid1 is $pid1, pid2 is $pid2\n"
expect_background $pid2
interact
puts "AFTER interact, script is exiting\n"

The other two scripts are:

# File t1.sh
#!/bin/bash
echo "Running script: $0"
date
ls
sleep 5
date

And

# File t2.sh
#!/bin/bash
echo "Running script: $0"
date
ls
sleep 10
date

While this runs, the interact doesn't work and I'm not sure how to direct waiting and sending commands to each spawned process.

The output I get is

starting 1
spawn_id is exp4, pid is exp4

starting 2
spawn_id is exp5, pid1 is exp4, pid2 is exp5
Running Script: ./t1.sh
Thu 21 Sep 2023 03:45:15 PM EDT
Running Script: ./t2.sh
Thu 21 Sep 2023 03:45:15 PM EDT
ex1.ex  t1.sh t2.sh 
ex1.ex  t1.sh t2.sh 
Thu 21 Sep 2023 03:45:20 PM EDT
Thu 21 Sep 2023 03:45:25 PM EDT
interact: spawn id exp5 not open
   while executing
"interact"
  (file "./ex1.ex" line 12)

Searching for a solution.

There were several questions around spawn but none addressed my question.

Some were


Solution

  • Here's an example shell script using my sexpect. In the script it lets Bash and Python work together to calculate sum(1..10).

    $ cat multi-spawn.sh

    bashexp() { sexpect -s /tmp/sexpect-bash-$$.sock "$@"; }
    pythexp() { sexpect -s /tmp/sexpect-pyth-$$.sock "$@"; }
    
    ps1bash='bash-[0-9.]+[$#] $'
    ps1pyth='>>> $'
    
    bashexp spawn bash --norc
    pythexp spawn python3
    
    bashexp expect -re "$ps1bash"; echo
    pythexp expect -re "$ps1pyth"; echo
    
    sum=0
    for ((i = 1; i <= 10; ++i)); do
        if ((i % 2)); then  # bash to add odd numbers
            bashexp expect -lookback 1
            bashexp send -enter "echo sum=\$(($sum + $i))"
            bashexp expect -re 'sum=([0-9]+)'
            sum=$( bashexp expect_out -i 1 )
    
            bashexp expect -re "$ps1bash"; echo
        else  # python to add even numbers
            pythexp expect -lookback 1
            pythexp send -enter "print('sum=%d' % ($sum + $i))"
            pythexp expect -re 'sum=([0-9]+)'
            sum=$( pythexp out -i 1 )
    
            pythexp expect -re "$ps1pyth"; echo
        fi
    done
    
    bashexp expect -lookback 1
    bashexp send -enter 'exit # Bash exiting ...'
    bashexp wait
    
    pythexp expect -lookback 1
    pythexp send -enter 'exit() # Python exiting ...'
    pythexp wait
    
    echo "---- Final sum: $sum ----"
    

    $ bash multi-spawn.sh

    bash-5.2$
    Python 3.11.5 [Clang 14.0.3] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>>
    bash-5.2$ echo sum=$((0 + 1))
    sum=1
    bash-5.2$
    >>> print('sum=%d' % (1 + 2))
    sum=3
    >>>
    bash-5.2$ echo sum=$((3 + 3))
    sum=6
    bash-5.2$
    >>> print('sum=%d' % (6 + 4))
    sum=10
    >>>
    bash-5.2$ echo sum=$((10 + 5))
    sum=15
    bash-5.2$
    >>> print('sum=%d' % (15 + 6))
    sum=21
    >>>
    bash-5.2$ echo sum=$((21 + 7))
    sum=28
    bash-5.2$
    >>> print('sum=%d' % (28 + 8))
    sum=36
    >>>
    bash-5.2$ echo sum=$((36 + 9))
    sum=45
    bash-5.2$
    >>> print('sum=%d' % (45 + 10))
    sum=55
    >>>
    bash-5.2$ exit # Bash exiting ...
    exit
    >>> exit() # Python exiting ...
    ---- Final sum: 55 ----