3

Is there a way to redirect stdin sent to expect such that it is fed to a spawn call within expect? In my example below I am embedding expect within a shell function to which I want to pipe another shell script via heredoc and supressing the output by capturing it to a shell variable.

    psshstdin() {
      local user=$1 pass=$2 hosts=$3
      out=$(expect -c '
      set timeout 15
      spawn pssh -i -h '"$hosts"' -p 100 -l '"$user"' -A -o ./ -x-oStrictHostKeyChecking=no <EXPECT_STDIN_HERE
      expect "assword:" { send '\""$pass\r\""' }
      interact
    '<<EOF
    echo "hello"
    echo "world"
    EOF
    )
    }

SOLUTION: I had to post this here since I don't have enough reputation points to answer my own question so quickly.

I was able to resolve it by trying the same techniques applied in this issue. I didn't think that solution was applicable initially, but it was. The working code is shown below.

psshstdin() {
  local user=$1 pass=$2 hosts=$3
out=$(expect -c '
set timeout 30
spawn pssh -I -h '"$hosts"' -p 100 -l '"$user"' -A -o ./ -x-oStrictHostKeyChecking=no
while {[gets stdin line] != -1} {
  send "$line\n"
}
send \004
expect "assword:" { send '\""$pass\r\""' }
expect {
  "END_TOKEN_OF_SCRIPT" {
    exit 0
  }
  default {
    exit 1
  }
}'<&0)
}

I can call it with something like:

psshstdin myusername mypassword ssh_hosts_file<<EOF
echo "hello"
echo "world"
EOF
Community
  • 1
  • 1
user1387661
  • 31
  • 1
  • 3

1 Answers1

0

You can capture stdin to a variable with stdin=$(cat -)

Update: let expect collect the stdin:

untested, but perhaps:

psshstdin() {
  local user=$1 pass=$2 hosts=$3
  out=$(expect -c '
    set stdin [read stdin]
    puts "debug: sending the following stdin to pssh:\n$stdin\n--END--"
    set timeout 15
    spawn echo "$stdin" | pssh -i -h '"$hosts"' -p 100 -l '"$user"' -A -o ./ -x-oStrictHostKeyChecking=no
    expect "assword:" { send "'"$pass"'\r" }
    interact
  '<<EOF
echo "hello"
echo "world"
EOF
)
}
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • 1
    This works within the shell, but there seems to be no documented way to pipe it into the command called by spawn. I tried the following in the context of the code in the original: `spawn echo '"$stdin"' | pssh.....` `spawn pssh...< '"$stdin"'` and neither can actually pipe the text in properly within expect. – user1387661 May 10 '12 at 17:32
  • you'll want to quote it within expect: `spawn pssh...< {'"$stdin"'}`. I'll provide an alternative in my answer. – glenn jackman May 10 '12 at 18:36
  • I realized the answer was sitting in an existing stackoverflow question the whole time. Thanks for the quick help though. – user1387661 May 10 '12 at 19:47
  • 3
    @user1387661, please add a comment to your question with a link to that other question, so others can benefit. – glenn jackman May 10 '12 at 20:07