Originally published January 7, 2018 @ 10:43 pm

A small collection of maybe helpful examples of how to use expect with Bash. This is a very useful tool, especially when writing a better script is just too much work, but the funky syntax gets me every time. I have various expect examples scattered throughout this site, so this is more of an attempt at organizing them.

Generate SSH keys

#!/bin/bash
export b=2048
export t=rsa
expect -c "
set timeout 5
spawn ssh-keygen -b ${b} -t ${t}
expect \"Enter file\" { send \"\r\" }
expect \"Enter passphrase\" { send \"\r\" }
expect \"Enter same passphrase\" { send \"\r\" }
expect eof"

Push SSH public key to node001-100

#!/bin/bash
export u=root
export p=rootpass
export h=node
for i in `seq -w 001 100`
do
	expect -c "
	set timeout 5
	spawn ssh-copy-id -i `grep ^${u}: /etc/passwd | awk -F: '{print $6}'`/.ssh/id_rsa.pub ${u}@${h}${i}
	expect \"Are you sure\" { send \"yes\r\" }
	expect \"ssword:\" { send \"${p}\r\" }
	expect eof"
done

Execute an arbitrary command on remote server via passwordless SSH

In this example, the uptime command will be executed on all nodes, but the “cat /etc/issue” command will only be executed on node030. Of course, this is not the right way of doing something like that – just an example.

export h=node
export u=root
for i in `seq -w 001 100`
do
	expect -c "
	set timeout 1
	spawn ssh -qt ${u}@${h}${i}
	expect \"#\" { send \"uptime\r\" }
	expect \"node030\" { send \"cat /etc/issue\r\" }
	expect eof" 2>/dev/null
done

Another example similar to the previous. In this case, we’re reading the list of hosts from a file and, after login, execute sudo su - and count the number of entries in the /etc/shadow file:

for i in `cat ~/hostlist`
do
   expect -c "
   set timeout 2
   spawn ssh -qt ${i}
   expect \">\" { send \"sudo su -\r\" }
   expect \"#\" { send \"wc -l /etc/shadow\r\" }
   expect eof" 2>/dev/null
done