Search code examples
linuxbashperlexpectubuntu-20.04

expect command is not passing env variable in ubuntu focal


I'm using expect (v5.45.4-2build1) to automate generation of client certs using easy-rsa in ubuntu focal. As per easy-rsa, to customize cert validity we need to pass EASYRSA_CERT_EXPIRE variable. But for some reason, my expect script is not able to fetch this variable. Here's the code for script.exp:

#!/usr/bin/expect -f

set timeout -1
#exp_internal 1

set MY_PASSPHRASE [lindex $argv 0];
set USERNAME [lindex $argv 1];
set ttl [lindex $argv 2];

send "export EASYRSA_CERT_EXPIRE=$ttl\r"
spawn /bin/bash

set MSG "Executing script.exp for $USERNAME and $ttl";
send "echo 'INFO $MSG'>> /var/log/app/my_app.log\r"

send "cd /etc/openvpn/easy-rsa\r"

send "export EASYRSA_CERT_EXPIRE=$ttl\r"

send "./easyrsa gen-req $USERNAME\r"
expect "*Enter PEM pass phrase:"
send -- "$MY_PASSPHRASE\r"
expect "*Verifying - Enter PEM pass phrase:"
send -- "$MY_PASSPHRASE\r"
expect "*Common Name *$USERNAME*"
send -- "\r"
expect "*Keypair and certificate request completed*"
send -- "\r"
exit 0

Strangely, this works fine if i run the script via expect script.exp. But I want to use this in my perl script and it is not working from the perl script.

This is how I'm calling my expect script:

my $cmd_out_csr = system("expect script.exp $my_passphrase $username $ttl");

Just running, expect script.exp $my_passphrase $username $ttl from cmd works fine. Any help is appreciated. Thanks.


Solution

    1. use the perl system command with a list of arguments:

      system('expect', 'script.exp', $my_passphrase, $username, $ttl);
      
    2. when creating the variable in the remote shell, send quotes around the value:

      send "export EASYRSA_CERT_EXPIRE=\"$ttl\"\r"
      

    These two things will protect the value of $ttl if it contains whitespace.


    Another thought: expect (via Tcl) can cd and set environment variables. Instead of spawning a bash shell, spawn easyrsa directly:

    #!/usr/bin/expect -f
    
    set timeout -1
    #exp_internal 1
    
    lassign $argv MY_PASSPHRASE USERNAME ttl
    
    set f [open /var/log/app/my_app.log a]
    puts $f "INFO Executing [info script] for $USERNAME and $ttl"
    close $f
    
    cd /etc/openvpn/easy-rsa
    set env(EASYRSA_CERT_EXPIRE) $ttl
    
    spawn ./easyrsa gen-req $USERNAME
    
    expect "*Enter PEM pass phrase:"
    send -- "$MY_PASSPHRASE\r"
    expect "*Verifying - Enter PEM pass phrase:"
    send -- "$MY_PASSPHRASE\r"
    expect "*Common Name *$USERNAME*"
    send -- "\r"
    expect "*Keypair and certificate request completed*"
    send -- "\r"
    expect eof
    
    puts "Done."