I have an expect script, and want to spawn a BASH command for it to provide input to. When I use the following syntax:

spawn /bin/bash docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki`


spawn docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki

I get the following error:

bad flag "-it": must be -glob, -regexp, -exact, -notransfer, -nocase, -i, -
indices, -iread, -timestamp, -timeout, -nobrace, or --
    while executing
"expect {
   spawn (/bin/bash) docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn 
   "Enter PEM pass phrase:"   {send "DefPEMVPNPassPhra..."
    (file "addcontainer.exp" line 7)

How do I tell expect to spawn a BASH command?


The syntax to access environment variables in TCL (expect is a TCL interpreter) is $env(VARNAME), so:

spawn docker run -v $env(OVPN_DATA):/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki

If you want to run a shell to interpret some shell code, you'd run sh -c the-code (or bash -c though there's nothing bash-specific in that shell code here). That's what the system() function of most languages to.

spawn sh -c {
  docker run -v "$OVPN_DATA:/etc/openvpn" --rm -it kylemanna/openvpn ovpn_initpki

{...} are the strong quotes in TCL. I also added the missing quotes around the shell variable expansion, as otherwise it would be more zsh/rc/fish syntax than sh syntax.

Also, you'd spawn before any expect ... statement. The spawn command is to launch the command you want to interact with, the expect ... statement is to wait for specific output from that command.

In your code above, you're not running spawn at all, that spawn inside the expect argument is take as a pattern to look for in the output of an earlier spawned command if any, or from stdin if not.

| improve this answer | |

The output suggests that spawn doesn't stop interpreting flags when it encounters a command name.

A common convention is to use -- as a separator between options for a command (which it should parse and interpret), and arguments to things it needs to call (which it should ignore and pass on).

The spawn output lists -- as one of the possible options, which suggests that it follows that convention. Try specifying it?

spawn /bin/bash -- -c "docker run ..."
| improve this answer | |
  • the -- probably shouldn't be placed after bash and before bash flags ... – thrig Feb 7 '18 at 17:56


spawn /bin/bash
send "docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn  ovpn_initpki"
| improve this answer | |
  • You will need to escape the $ as tcl will expand this within "". Or you can replace the double quotes by {} quotes. – meuh Feb 7 '18 at 16:51
  • It's also possible that the quoting can be dropped, and just the -c will be enough to load up bash. Or maybe just quote "docker", though that may not take care of how tcl will handle the variable definitions within the expect file. – John Feb 7 '18 at 16:53
  • bad flag "-c": must be -glob, -regexp, -exact, -notransfer, -nocase, -i, -indices, -iread, -timestamp, -timeout, -nobrace, or -- – William Edwards Feb 7 '18 at 17:20
  • The error that you are reporting is from expect. I updated my answer – John Feb 7 '18 at 17:52
  • @JohnW.Gill Not sure what's going on. No errors when I use that code but the container shows many errors saying that the configuration files don't exist (that are created with that input). I'll investigate further. – William Edwards Feb 7 '18 at 19:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.