简体   繁体   English

如何使用Expect内部循环遍历Bash数组?

[英]How to loop over Bash array using expect inside?

I'm trying to loop over a Bash array (list of packages), and inside the loop use some expect commands to automate interactive inputs. 我正在尝试遍历Bash数组(软件包列表),并且在循环内使用一些expect命令来自动执行交互式输入。

The script should ask few questions to provide a pass phrase and a path where rpm packages are stored. 该脚本应该问几个问题,以提供一个密码短语和一个存储rpm软件包的路径。 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. 之后,从列表和循环器组成数组,以签名rpm软件包(使用用于自动密码输入的expect代码)并将软件包推送到RedHat Satellite。

The loop is not working and I can't export correctly the array to expect . 循环不起作用,我无法正确导出expect的数组。

``` Updated code after Glenn's recommendations. ``` 根据Glenn的建议更新了代码。

#/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. 更新2:我继续致力于此问题,以使其得到解决。 I hard coded the bash variables for convenience. 为了方便起见,我对bash变量进行了硬编码。 I almost figured it out, the obvious not working thing still the environment variable from bash. 我几乎弄清楚了,显然不起作用的东西仍然是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. Expect脚本可以正确解释它,但是如果我用文件名替换变量,则可以以某种方式生成' 无法访问文件 '(意味着它无法找到文件)。

#/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! 提前致谢!

Inside expect, 内心期待

  • you get environment variables with $env(PASSPHRASE) . 您可以使用$env(PASSPHRASE)获得环境变量。
  • You're already in the global scope there, so global ::env is redundant (actually doubly redundant with the fully qualified ::env ). 您已经在全局范围内了,所以global ::env是多余的(实际上对于完全合格的::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. 摆脱使用ALLCAPSVARNAMES的习惯,如果不小心使用“保留”变量名,可能会惹上麻烦。

  • it seems strange to use the read option -e with -s -- hard to edit something you can't see. -s使用read选项-e似乎很奇怪-很难编辑看不见的内容。
  • "array" is a poor variable name for an element of an array. “数组”是数组元素的较差的变量名。

In your case, PLIST is not an array, you need to convert it to array. 在您的情况下,PLIST不是数组,您需要将其转换为数组。 Put the line below before the for loop (line 6) 将下面的行放在for循环之前(第6行)

PLIST=( $PLIST )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM