Search code examples
pipeexpectsendargvspawn

expect command variable with pipes and special characters not working


I have trouble trying to send a command to a remote server using an expect script. The command is Ok if I insert it in the send command manually in the script, but it's not working if I pass it to the except script through an argument ( $command). The command I want to run in the remote server is:

top -b -n 2 | head -15 && ls -lrt /var/log | head -10

EXAMPLE: ./myexpectscript password ip "top -b -n 2 | head -15 &"

UPDATE: I find out that every command I send (that is more than a single string ) through this script in the remote server is executed within braces... FOR EXAMPLE:

./myexpectscript password ip "pwd" is ok

./myexpectscript password ip "echo hello" the answer is:

# {echo hello}
/bin/sh: {echo: not found

If I remove the double quotes the command works:

./myexpectscript password ip echo hello

# echo hello
hello

So, the problem is that I want to execute a multiple piped single line command:

top -b -n 2 | head -15 && ls -lrt /var/log | head -10

on the server through my except script I got :

  # {top -b -n 2 | head -15 && ls -lrt /var/log | head -10}
  /bin/sh: {top: not found
  ls: /var/log: No such file or directory
  head: invalid number '10}'

this should work with double quotes but I got the command in braces. I tried this script on other servers of different type and I got the same behavior.

#!/usr/bin/expect -f
set password [lrange $argv 0 0]
set ipaddr [lrange $argv 1 1]
set command [lrange $argv 2 end]
set timeout -1
spawn ssh admin@$ipaddr
match_max 100000
expect "*?assword:*"

send -- "$password\r"

expect "*\\\[0-7\\\]:*"
send -- "5\r"

expect "*\\\[0-4\\\]:*"
send -- "3\r"

expect "\\\#*"

#spawn {*}$command
#eval spawn $command
#send --  "$command\r"
send --  "top -b -n 2 | head -15 && ls -lrt /var/tslog | head -10\r"

expect "\\\#*"
send -- "exit\r"

expect "*\\\[0-4\\\]:*"
send -- "0\r"

expect "*\\\[0-7\\\]:*"
send -- "0\r"


expect eof

Solution

  • Use lindex instead of lrange:

    #!/usr/bin/expect -f
    set password [lindex $argv 0]
    set ipaddr   [lindex $argv 1]
    set command  [lindex $argv 2]
    ... ...
    send -- "$command\r"
    

    And call your script this way:

    ./myexpectscript password ip "echo hello world"