skip to Main Content

I’m writing a script to remotely install linux software updates (which use a .bin updater tool) using Expect. I’m having trouble matching one block, and I’ve tried a bunch of variations with no success. I’ve gotten other similar scripts to work, but I’ve used wildcards to match newlines, and in this case, I need to make sure the list of files is exactly what I’m expecting, so I didn’t want to break it up with any wildcards that could hide a mismatch.

Can someone take a look and tell me what I’m doing wrong?

Console output, plain

Checking for local modifications.

List of modifications made within Jira directories.

The following provides a list of file modifications within the
atlassian-jira directory.

Modified files:
    atlassian-jira/WEB-INF/classes/seraph-config.xml
    bin/setenv.sh
    conf/server.xml
Removed files:
    (none)
Added files:
    atlassian-jira/WEB-INF/classes/crowd.properties

[Enter]

My latest attempt to match it and send Enter (line breaks only added to Stack Overflow, not present in script

expect {*Checking for local modifications*Modified files:rntatlassian-jira/WEB-INF/classes/seraph-config.xmlrntbin/setenv.shrntconf/server.xmlrnRemoved files:rnt(none)rnAdded files:rntatlassian-jira/WEB-INF/classes/crowd.propertiesrnrn[Enter]}

When I run through expect with the -d flag, this is what it prints:

expect: does "rnnrnrnChecking for local modifications.rnrnList of modifications made within Jira directories.rnrnThe following provides a list of file modifications within thernatlassian-jira directory.rnrnModified files:rntatlassian-jira/WEB-INF/classes/seraph-config.xmlrntbin/setenv.shrntconf/server.xmlrnRemoved files:rnt(none)rnAdded files:rntatlassian-jira/WEB-INF/classes/crowd.propertiesrnrn[Enter]rn" (spawn_id exp5) match glob pattern "*Checking for local modifications*Modified files:rntatlassian-jira/WEB-INF/classes/seraph-config.xmlrntbin/setenv.shrntconf/server.xmlrnRemoved files:rnt(none)rnAdded files:rntatlassian-jira/WEB-INF/classes/crowd.propertiesrnrn[Enter]"? no

I’m running from an outer bash script like so:

#!/usr/bin/env bash
set -e

sudo expect -d << EOD
    spawn ${INSTALLER_PATH}

    expect_before timeout { exit 1 }

    expect {Match phrase} {
        send -- "r"
    }

    ...

    expect eof

EOD

** Update 4/5/2021 **

I tried @pynexj’s suggestion to use "" instead of {} to surround my expression (below), it still doesn’t work.

New script

sudo expect -d << EOD
    ...
    expect "rnnrnrnChecking for local modifications.rnrnList of modifications made within Jira directories.rnrnThe following provides a list of file modifications within thernatlassian-jira directory.rnrnModified files:rntatlassian-jira/WEB-INF/classes/seraph-config.xmlrntbin/setenv.shrntconf/server.xmlrnRemoved files:rnt(none)rnAdded files:rntatlassian-jira/WEB-INF/classes/crowd.propertiesrnrn[Enter]rn" {
        send -- "r"
    }

    expect eof

EOD

I ran the debug output I received through Beyond Compare and the two strings printed out match each other 100%.

Updated debug output

expect: does "rnnrnrnChecking for local modifications.rnrnList of modifications made within Jira directories.rnrnThe following provides a list of file modifications within thernatlassian-jira directory.rnrnModified files:rntatlassian-jira/WEB-INF/classes/seraph-config.xmlrntbin/setenv.shrntconf/server.xmlrnRemoved files:rnt(none)rnAdded files:rntatlassian-jira/WEB-INF/classes/crowd.propertiesrnrn[Enter]rn" (spawn_id exp5) match glob pattern "rnnrnrnChecking for local modifications.rnrnList of modifications made within Jira directories.rnrnThe following provides a list of file modifications within thernatlassian-jira directory.rnrnModified files:rntatlassian-jira/WEB-INF/classes/seraph-config.xmlrntbin/setenv.shrntconf/server.xmlrnRemoved files:rnt(none)rnAdded files:rntatlassian-jira/WEB-INF/classes/crowd.propertiesrnrn[Enter]rn"? no

Two strings on top of each other

You can scroll these sideways in Stack Overflow to see they match 100%:

# command output on top
rnnrnrnChecking for local modifications.rnrnList of modifications made within Jira directories.rnrnThe following provides a list of file modifications within thernatlassian-jira directory.rnrnModified files:rntatlassian-jira/WEB-INF/classes/seraph-config.xmlrntbin/setenv.shrntconf/server.xmlrnRemoved files:rnt(none)rnAdded files:rntatlassian-jira/WEB-INF/classes/crowd.propertiesrnrn[Enter]rn
rnnrnrnChecking for local modifications.rnrnList of modifications made within Jira directories.rnrnThe following provides a list of file modifications within thernatlassian-jira directory.rnrnModified files:rntatlassian-jira/WEB-INF/classes/seraph-config.xmlrntbin/setenv.shrntconf/server.xmlrnRemoved files:rnt(none)rnAdded files:rntatlassian-jira/WEB-INF/classes/crowd.propertiesrnrn[Enter]rn
# Expect expression underneath

2

Answers


  1. Chosen as BEST ANSWER

    I needed to make two changes to get it to match:

    1. As @pynexj suggested, I needed to surround my expression with "" instead of {}
    2. I also needed to pass the -ex argument to the expect command or else it would still not match, even though the debug output indicated character by character that the output matched the expectation

    This is what I ended up with, making it as readable as possible:

    sudo expect << EOD
        spawn ${INSTALLER_PATH}
    
        ...
    
        expect {*Back up Jira home directory?*Yes [y], No [n, Enter]} {
            send -- "nr"
        }
    
        expect -ex "rn
    nrn
    rn
    Checking for local modifications.rn
    rn
    List of modifications made within Jira directories.rn
    rn
    The following provides a list of file modifications within thern
    atlassian-jira directory.rn
    rn
    Modified files:rn
        atlassian-jira/WEB-INF/classes/seraph-config.xmlrn
        bin/setenv.shrn
        conf/server.xmlrn
    Removed files:rn
        (none)rn
    Added files:rn
        atlassian-jira/WEB-INF/classes/crowd.propertiesrn
    rn
    [Enter]rn
    " {
            send -- "r"
        }
    
        expect eof
    
    EOD
    

  2. In Tcl, backslash escaped strings (like rn) embedded in braces ({}) has no special meaning. You should use double quotes here.

    $ tclsh
    % puts {footbarrn}
    footbarrn
    % puts "footbarrn"
    foo     bar
    
    %
    

    According to Tcl doc:

    • [6] Braces.

      If the first character of a word is an open brace ({) and rule [5] does not apply, then the word is terminated by the matching close brace (}). Braces nest within the word: for each additional open brace there must be an additional close brace (however, if an open brace or close brace within the word is quoted with a backslash then it is not counted in locating the matching close brace). No substitutions are performed on the characters between the braces except for backslash-newline substitutions described below, nor do semi-colons, newlines, close brackets, or white space receive any special interpretation. The word will consist of exactly the characters between the outer braces, not including the braces themselves.

    But note that when you use double quotes. To match [Enter] you need to write \[Enetr\] because by default the expect statement uses glob-style matching. For example:

    $ expect -c 'spawn -noecho bash -c {echo "[Enter]"}; expect eof'
    [Enter]
    $ expect -c 'spawn -noecho bash -c {echo "[Enter]"}; expect "\[Enter\]"; expect eof'
    [Enter]
    $ expect -c 'spawn -noecho bash -c {echo "[Enter]"}; expect -ex "[Enter]"; expect eof'
    [Enter]
    $
    

    UPDATE:

    Just noticed you are using Bash’s here doc. Then you have to do one more level quoting.

    $ expect << EOF
    > spawn -noecho bash -c {echo "[Enter]"}
    > expect "\\\[Enter\\\]"
    > expect eof
    > EOF
    [Enter]
    $
    

    Or you can use << "QUOTED_STRING_HERE":

    $ expect << 'EOF'
    > spawn -noecho bash -c {echo "[Enter]"}
    > expect "\[Enter\]"
    > expect eof
    > EOF
    [Enter]
    $
    

    According to man bash, for << word:

    If any part of word is quoted, the delimiter is the result of quote
    removal on word, and the lines in the here-document are not expanded.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search