1

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
  • @steeldriver No, I'm getting can't read "argv": no such variable :( – Katie Mar 2 '18 at 1: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 2 '18 at 1:37
3

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...

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

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.