1

I'm trying to loop over a Bash array (list of packages), and inside the loop use some expect commands to automate interactive inputs.

The script should ask few questions to provide a pass phrase and a path where rpm packages are stored. After that, the array is formed from the list and looper over to sign rpm packages (using expect code for automatic passphrase input) and push packages to RedHat Satellite.

The loop is not working and I can't export correctly the array to expect.

```Updated code after Glenn's recommendations.

#/bin/bash
read -srep $'Please, insert passphrase:\n\n' PASSPHRASE
read -rep $'Please, provide a path for your package(s) being signed and  pushed:\#n\n' PPATH
mapfile PLIST < <(find "$PPATH" -name "*.rpm")
export PASSPHRASE PLIST
for package in "${PLIST[@]}"
do
        echo "$package"
        export package
        /usr/bin/expect<<EOF 

        set force_conservative 0 ;
                             ;
        set filename [lindex $argv 0]
        set timeout -1
        spawn rpm --resign $::env(package)
        close $spawn_id
        expect "*phrase:"
        send -- "$PASSPHRASE\r" 
        expect eof
EOF
done
unset PASSPRASE

And here is what I get:

spawn rpm --resign x86_64/myrpm9.rpm

expect: spawn id exp4 not open
    while executing
"expect "*phrase:""

spawn rpm --resign x86_64/myrpm1.rpm

expect: spawn id exp4 not open
    while executing
"expect "*phrase:""

UPDATE 2: I continued to work on this to try to get it fixed. I hard coded the bash variables for convenience. I almost figured it out, the obvious not working thing still the environment variable from bash. The expect script interpretes it correctly, but spawn somehow give 'cannot access file' (meaning it can't find the file) if I substitute variable with file name it works.

#/bin/bash
PASSPHRASE="IamPass"
PPATH="/home/user/strcompat-debuginfo-0.9.2.7-1.x86_64.rpm"
mapfile PLIST < <(find "$PPATH" -name "*.rpm")
export PASSPHRASE PLIST
for package in "${PLIST[@]}"
do
        export package
        /usr/bin/expect -d  <<EOF 
        set force_conservative 0 ;
        set filename [lindex $argv 0]
        set timeout -1
        spawn rpm --resign $::env(package)
        expect {  "*phrase:"
        { send -- "$PASSPHRASE\r"; incr i; exp_continue }
        eof exit
        }
EOF
done

Output in debug mode:

[user@linuxbox ~]$ ./script.sh 
expect version 5.44.1.15
argv[0] = /usr/bin/expect  argv[1] = -d  
set argc 0
set argv0 "/usr/bin/expect"
set argv ""
executing commands from command file
spawn rpm --resign /home/user/strcompat-debuginfo-0.9.2.7-1.x86_64.rpm

parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {18487}

expect: does "" (spawn_id exp4) match glob pattern "  "*phrase:"\n\t{ send -- "IamPass\r"; incr i; exp_continue }\n\t# close \n\teof exit\n\t"? no
cannot access file /home/user/strcompat-debuginfo-0.9.2.7-1.x86_64.rpm


expect: does "cannot access file /home/user/strcompat-debuginfo-0.9.2.7-1.x86_64.rpm\r\n\r\n" (spawn_id exp4) match glob pattern "  "*phrase:"\n\t{ send -- "IamPass\r"; incr i; exp_continue }\n\t# close \n\teof exit\n\t"? no
expect: read eof
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "cannot access file /home/user/strcompat-debuginfo-0.9.2.7-1.x86_64.rpm\r\n\r\n"

Normal output:

[user@linuxbox ~]$ ./script.sh 
spawn rpm --resign /home/user/strcompat-debuginfo-0.9.2.7-1.x86_64.rpm

cannot access file /home/user/strcompat-debuginfo-0.9.2.7-1.x86_64.rpm

[user@linuxbox ~]$ echo $?
0

Any you advice will be much appreciated! Thanks in advance!

4
  • Benjamin W., thanks for edits. Commented Feb 25, 2016 at 10:10
  • Can you explain why you're closing spawn_id immediately after spawning? Commented Mar 3, 2016 at 1:34
  • Well, true.I only put it there due the fact that if i put it after send -- "$PASSPHRASE\r" it fails with: spawn rpm --resign x86_64/myrpm0.rpm cannot access file x86_64/myrpm0.rpm send: spawn id exp4 not openwhile executing "send -- "plain_passphrase_here!\r" Commented Mar 3, 2016 at 15:12
  • Hi Glenn. Was again playing with this script (need to finish it up), though without luck. Can you maybe advise on mistakes, solutions? Thanks! Commented Apr 17, 2016 at 16:34

2 Answers 2

1

Inside expect,

  • you get environment variables with $env(PASSPHRASE).
  • You're already in the global scope there, so global ::env is redundant (actually doubly redundant with the fully qualified ::env).

In bash,

  • to read lines into an array you would do

    mapfile PLIST < <(find "$PPATH" -name "*.rpm")
    
  • get out of the habit of using ALLCAPSVARNAMES, that can get you in trouble if you accidentally use a "reserved" variable name.

  • it seems strange to use the read option -e with -s -- hard to edit something you can't see.
  • "array" is a poor variable name for an element of an array.
Sign up to request clarification or add additional context in comments.

1 Comment

Hi Glenn! Thanks for another your reply to my question. I did try to play with the recommened by you solution and almost succeed, The loop is working as well as the environment variables.Though there are some issues stilll... P.S. I've updated initial post with new version of script and output. Thanks!
0

In your case, PLIST is not an array, you need to convert it to array. Put the line below before the for loop (line 6)

PLIST=( $PLIST )

2 Comments

Hi. Thanks, actually I did try that, wasn't much of the difference as I still wasn't been able to properly propagate/set and use array to expect.
Maybe you should comment all contents inside the for loop, then replace it by a simple command (for example: echo), then test if the loop works fine

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.