4

I'm using expect inside my bash script by using expect -c, but how do I pass parameters to it?

This is what I've tried:

FILE="myFile"
HOST="myhostname" 

/usr/bin/expect -c $FILE $HOST '
        set FILE [lindex $argv 0];
        set HOST [lindex $argv 1];
        send_user "$FILE $HOST"
        spawn scp -r -o StrictHostKeyChecking=no  $FILE root@$HOST:/tmp/
        expect "assword:"
        send "password\r"
        interact'

If I create a separate expect script with the same contents but call it in bash like this:

myScript.expect $FILE $HOST

It works, but how do I do the same thing but using the expect -c option?

Update:

Also tried:

/usr/bin/expect -c '
        set FILE [lindex $argv 0];
        set HOST [lindex $argv 1];
        send_user "$FILE $HOST"
        spawn scp -r -o StrictHostKeyChecking=no  $FILE root@$HOST:/tmp/
        expect "assword:"
        send "password\r"
        interact' $FILE $HOST
Katie
  • 1,562
  • @steeldriver No, I'm getting can't read "argv": no such variable :( – Katie Mar 02 '18 at 01:16
  • I don't know about expect, but your command string is single quoted, so $FILE and $HOST won't expand in it. – muru Mar 02 '18 at 01:37

1 Answers1

5

You cannot. In the source code for expect-5.45.4 we find in exp_main_sub.c at line 711

            case 'c': /* command */
                    exp_cmdlinecmds = TRUE;
                    rc = Tcl_Eval(interp,optarg);
                    ...

which handles -c code. $argv and friends are only created after the -c eval completes down at line 850 onwards

    /* collect remaining args and make into argc, argv0, and argv */
    sprintf(argc_rep,"%d",argc-optind);
    Tcl_SetVar(interp,"argc",argc_rep,0);
    expDiagLog("set argc %s\r\n",argc_rep);

    ...
    Tcl_SetVar(interp,"argv",args,0);

so $argv absolutely does not exist when the -c code runs.

One workaround is Run a local expect script on a remote server? which entails passing the TCL code in on standard input and then reading in expect the file /dev/stdin

$ echo puts \[lindex \$argv 1\] | expect /dev/stdin blee bla blu
bla

Another workaround is to toss the shell and write the whole thing in TCL

#!/usr/bin/env expect
set FILE [lindex $argv 0]
set HOST [lindex $argv 1]
...

And then chmod +x that and run it

./whatyoucalledtheabove somefile somehost

It would need to contain whatever else your current shell script does above the expect call...

thrig
  • 34,938
  • Bummer, alrighty I'll create a separate script and call that. Thank you for the detailed explanation! – Katie Mar 02 '18 at 17:16