Search code examples
bashshellexpectheredocquoting

How to make expect nested in the bash script properly?


Here is the expect file which can run succesfully.

#!/usr/bin/expect  -f
set host vps_ip
set user test
set loginpwd  passwd
set adminpwd  passwd
set timeout 300
set prompt "#|>|\\\$"    
spawn scp  /home/wpdatabase_backup.sql   $user@$host:/tmp
expect -nocase  "password:"
send "$loginpwd\r"
expect eof
spawn  ssh  $user@$host
expect -nocase "password:"
send "$loginpwd\r"
expect -re $prompt
send "su\r"
expect  "assword:"
send "$adminpwd\r"
expect -re $prompt
send "mysql -u root -pxxxx wpdatabase < /tmp/wpdatabase_backup.sql\r"
expect eof

Here is the bash file:

mysqlword="xxxx"
mysqldump -u root -p$mysqlword wpdatabase > /home/wpdatabase_backup.sql

Now i want to make the expect file nested in the bash file because the bash file is more complicated than expect file ,most lines in the bash file were omitted.

code:

#!/usr/bin/bash
mysqlword="xxxx"
mysqldump -u root -p$mysqlword wpdatabase > /home/wpdatabase_backup.sql    
/usr/bin/expect <<EOD
set host vps_ip
set user test
set loginpwd  passwd
set adminpwd  passwd
set timeout 300
set prompt "#|>|\\\$"

spawn scp  /home/wpdatabase_backup.sql   $user@$host:/tmp
expect -nocase  "password:"
send "$loginpwd\r"
expect eof
spawn  ssh  $user@$host
expect -nocase "password:"
send "$loginpwd\r"
expect -re $prompt
send "su\r"
expect  "assword:"
send "$adminpwd\r"
expect -re $prompt
send "mysql -u root -pxxxx wpdatabase < /tmp/wpdatabase_backup.sql\r"
expect eof
<<EOD

An error occur : spawn scp /home/wpdatabase_backup.sql @:/tmp
ssh: Could not resolve hostname : Name or service not known
lost connection
send: spawn id exp6 not open
while executing
"send "\r""

Quote the terminator:

cat<<'EOD'
set host vps_ip
set user test
spawn scp  /home/wpdatabase_backup.sql   $user@$host:/tmp
EOD

Result:

set host vps_ip
set user test
spawn scp  /home/wpdatabase_backup.sql   $user@$host:/tmp

But how to make the output of result run in bash?

/usr/bin/expect  <<cat<<'EOD'
set host vps_ip
set user test
spawn scp  /home/wpdatabase_backup.sql   $user@$host:/tmp
EOD

The code can't run!


Solution

  • This is because in a here-document with an unquoted terminator like EOD, parameter substitution is performed by the shell. You can see that if you replace /usr/bin/expect with cat:

    $ cat<<EOD
    set host vps_ip
    set user test
    spawn scp  /home/wpdatabase_backup.sql   $user@$host:/tmp
    EOD
    

    Result:

    set host vps_ip
    set user test
    spawn scp  /home/wpdatabase_backup.sql   @:/tmp
    

    So, how to avoid parameter substitution? Quote the terminator:

    $ cat<<'EOD'
    set host vps_ip
    set user test
    spawn scp  /home/wpdatabase_backup.sql   $user@$host:/tmp
    EOD
    

    Result:

    set host vps_ip
    set user test
    spawn scp  /home/wpdatabase_backup.sql   $user@$host:/tmp