When I was a graduate Comp Sci TA in the 1990's, it was the perfect way to automate grading the Unix shell that the Systems Software class was supposed to write. Effectively, I was also writing a regression/functional testing system for the class. I explained that the Expect/Tcl script was going to be used to grade their project, and I provided the code.
One of my students said I was the best TA ever! There were a few students who complained that they shouldn't be marked off for a feature breaking, because it had worked a week or two ago. There were a few students who never figured out that the script was going to be used to grade their project, even though I provided weekly email updates explaining this.
If it's deterministic, is there a risk of someone just writing a second Expect script (instead of a solution to the programming exercise) that interacts with yours and gives the replies that you want?
Early on there was one or two cases where subtle problems came up because the public set and private set accidentally tested things slightly differently, but the TA / prof was quick to respond.
I got about 2 assignments into the class before I realized that I was being a chump. I wrote a C program that simply printed out the expected output, and submitted it. I received a passing grade on the assignment, so I took it further. I wrote a Perl script which would submit "int main(void){return 0;}", read the expected output, generate a C file that printed out that output, and submit it again.
Apparently the TA for the class never checked the submitted assignments and relied entirely on the submit program, so I was uncaught for a few weeks. My downfall was trying to make the Perl script as efficient as possible (I had extra time on my hands because I didn't have to do the C assignments!). I had run my Perl script a few dozen times while optimizing it, and apparently the TA received an email every time an assignment was submitted. He brought it up to the professor and I was called into his office. Luckily he was lenient and let me just redo the assignments :)
If you have a slave device over RS232, expect is probably your only option. But if that remote item is running sshd, you are way better off without expect.
Hence keys silently not working without "correct" permissions, passwords not passable on the CLI, inconsistent type-yes-to-override behavior, and other user-hostile design choices.
I love openssh, but it's a real pain in the ass sometimes.
Well, I maintain that the characters in the stream aren't as good success criterion as the stack of exit codes among the tasks. So if I "ssh remotefoo /tests/the_test.sh" it is the_test.sh's job to return 0 if it succeeded and nonzero otherwise. ssh will return 0 if the remote script returns zero, so I can count on that. But if the host is busy sometimes and the_test.sh takes 91 seconds on a heavily-loaded day but 37-45 seconds normally, I might encode the wrong timeout in my expect script. Things like /etc/issue or /etc/motd or PS1 should have no bearing on my test results. But if someone writes the text "Password:" or "Username:" or some other similar content in there, my expect script might choke on it.
It results in code like this:
https://github.com/ianmiell/shutit-chef-env/blob/master/shut...
which sets up a chef server.
[1] https://github.com/ianmiell/shutit-chef-env/blob/master/shut...
https://github.com/ip2k/Mad-Science?files=1
I wrote this a long time ago and it's ugly. It totally worked and let our company find more optimal hosting configs.
"Things Only 90s SysAdmins Will Remember"
Expect is mostly a tool of last resort when a utility has silly prompts that you can't bypass by hitting it with command line options like `-y` and stuff.
Fabric itself is a poor man's badly implemented RPC for sysadmins: you send commands and receive output and result codes. Fabric wraps this in a Python API, so you can react to how your operations run.
Salt and Ansible are similar to Fabric (and "poor man's badly implemented RPC" comment applies to them as well), but they also define some higher level tasks, like "have X package installed". All three have the operations defined at the call initiator and return synchronously, when all the work is done.
Then there are CFEngine, Puppet, and Chef. Every managed server runs an agent that periodically executes some rules. CFEngine and Puppet have their own DSLs, and Chef uses general purpose language (Ruby), what I consider a bad fit. These work asynchronously, as you don't push the rules to the servers, but change them in their distribution point and wait for servers to pick up the update.
Also:
1. I had read much of Don Libes' Expect book. He had a unique style of writing in that book. Hard to describe, partly since it was some years ago, and partly because I can't find the words for it. But I think anyone reading the book would notice the style after reading a few pages. It was not a bad style by any means, just ... something different.
2. I've read that expect was (maybe still is) used heavily in the electronics/EDA industry, though I am either not sure or don't remember how exactly they use it, or rather, for what. And also maybe it was used heavily by GNU software for testing. Maybe someone here can confirm.