简体   繁体   中英

Use of expect to run scripts on remote machine

I am working on a project that requires some assistance.

I have automated most of the information required for the completion of this project but the only thing that is lagging is the running of local shell scripts on the remote machine. As we are aware that no Linux command is recognized by the script that uses the 'expect' library. Herein we have two use cases that I have tried:

1) Running the desired list of commands on the remote server using only one expect script which has both the script execution as well as pushing of output using scp to the local machine, here is a snippet of this code:

`chmod 777 localscript.sh   
cat > script1.sh <<- "ALL"`  
`#!/usr/bin/expect
set password [lindex $argv 0];  
set ipaddress [lindex $argv 1];  
set timevalue [lindex $argv 2];  
set timeout $timevalue  
spawn /usr/bin/ssh username@$ipaddress /bin/bash < ./localscript.sh  
expect "assword:"  
send "$password\r"  
set timeout $timevalue  
spawn /usr/bin/scp username@$2:"/path/from/source/*" /path/to/destination/folder/  
expect "assword:"  
send "$password\r"  
interact  
ALL  
chmod 777 script1.sh  
./script1.sh $password $2 $timevalue`  

2) Running the desired list of commands on the remote server in a separate expect script and using scp to get files in a different script:

`cat > script1.sh <<- "ALL" ` 
`#!/usr/bin/expect
set password [lindex $argv 0];  
set ipaddress [lindex $argv 1];  
set timevalue [lindex $argv 2];  
set timeout $timevalue   
spawn /usr/bin/ssh username@$ipaddress /bin/bash < ./localscript.sh  
expect "assword:"  
send "$password\r"  
interact  
ALL  
cat > script2.sh <<- "ALL2"`  
`#!/usr/bin/expect
set password [lindex $argv 0];  
set ipaddress [lindex $argv 1];  
set timevalue [lindex $argv 2];  
set timeout $timevalue   
spawn /usr/bin/scp username@ipaddress:"/path/from/source/*" /path/to/destination/folder/  
expect "assword:"  
send "$password\r"  
interact  
ALL2  
chmod 777 localscript.sh script1.sh script2.sh   
./script1.sh  $password $2 $timevalue  
sleep 5  
./script2.sh  $password $2 $timevalue`

I believe the above codes should both be valid in their own respect however, the output for the same seem to be quite unexpected:

1) Both the commands ssh and scp are being executed almost simultaneously after password is entered hence, it is not giving localscript enough time to do its job, here's the output I see:

    spawn /usr/bin/ssh username@1.2.3.4 /bin/bash < ./localscript.sh  
    Warning private system unauthorized users will be prosecuted.  
    username@1.2.3.4's password: spawn /usr/bin/scp 
    username@1.2.3.4:"/home/some/file/*" /another/file/  
    Warning private system unauthorized users will be prosecuted.  
    username@1.2.3.4's password:  
    scp: /home/some/file/*: No such file or directory  

Please note: This functionality is working fine without the involvement of expect

2) Here we are executing ssh and scp separately, however, it seems like it is unable to recognize that the file localscript.sh exists:

    spawn /usr/bin/ssh username@1.2.3.4 /bin/bash < ./localscript.sh  
    Warning private system unauthorized users will be prosecuted.  
    username@1.2.3.4's password:  
    bash: localscript.sh: No such file or directory  
    Warning private system unauthorized users will be prosecuted.  
    username@1.2.3.4's password:  
    scp: /home/some/file/*: No such file or directory  

Any feedback on the same would be appreciated, I think the first approach might be a feasible solution, except the fact that spawn is too fast and none of the 'sleep' or 'after' commands are helping/working. I think the second approach is also valid however it seems like there is a different way of running a local script on a remote server than the usual way we do on Linux when using 'expect'.

Sorry for so much elaboration, I am hoping to be out of my misery soon :)

Indeed the timeout you are setting is not working as you expect it to. Both scripts are spawned, and the expect "assword:" after each spawn is actually catching and reacting to the same password prompt.

expect is actually more sophisticated than a cursory glance would lead you to believe. Each spawn should return a PID, which you can use with your expect to look for output from a specific process.

expect can also be broken down into multiple parts, and have the ability to define subroutines. Here are some more advanced use examples https://wiki.tcl-lang.org/10045

In this specific case I would suggest waiting for the scp to complete before spawning the next process.

expect {
    "assword:" {
        send "$password\r"
        exp_continue # Keep expecting
    }
    eof {
        puts -nonewline "$expect_out(buffer)"
        # eof so the process should be done
        # It is safe to execute the next spawn
        # without exp_continue this expect will
        # break and continue to the next line
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM