0
#!/bin/bash

# more commands here

expect << EOD
spawn telnet localhost 9151
expect -exact "Trying 127.0.0.1...\r
Connected to localhost.\r
Escape character is '^]'.\r"
send -- "AUTHENTICATE $COOKIE\r"
expect -exact "250 OK\r"
send -- "SIGNAL NEWNYM\r"
expect -exact "250 OK\r"
send -- "GETINFO circuit-status\r"
expect "250 OK\r"
send -- "QUIT\r"
expect -exact "250 closing connection\r
Connection closed by foreign host.\r"
EOD

# more commands here

This is about Expect. The script above establishes a telnet connection to the tor client and after clearing the current circuits, it gets the new circuit status.

GETINFO circuit-status outputs something like

250+circuit-status=
7 BUILT $D313CCBD93E756A53CD667D0A1A97E82B7740067~melco,$DA24B9CD2AA8C02B9068A168C420DC302D969937=TorExit1488,$C00DE13988B4ABC93B43617C0FADAA8E1D4A0293=nabtor BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2014-02-09T13:11:29.264485
5 BUILT $9DD5F90D641D835C4FCA7153148B156E6FD49CEE=darwinfish,$B013CA64C82EDC616BB3EC5DBE35BB7344EDFC2A=sipsrelay,$A59E1E7C7EAEE083D756EE1FF6EC31CA3D8651D7=chaoscomputerclub19 BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2014-02-09T13:11:05.263323
4 BUILT $5B8CCA69DFD88B0281D5E67C7764CA6B5177F210=IchGebDirNeuland,$A587BBB611657B0743CD9E6E70B6497BE209FFD2=RelayW,$D313B081A3EFC5492BE95AFE39F715413DD35586=ToileLibre BUILD_FLAGS=IS_INTERNAL,NEED_CAPACITY,NEED_UPTIME PURPOSE=GENERAL TIME_CREATED=2014-02-09T13:11:04.263266
2 BUILT $9DD5F90D641D835C4FCA7153148B156E6FD49CEE=darwinfish,$F16658975D729B8C4100A6DC649C5EDCAD1687A8=afo8,$35F51DCE73B988CBAE06B06312B4D1271979FE3B=thoreau BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2014-02-09T13:11:02.272687
.
250 OK

I checked the man page, Exploring Expect - A Tcl-based Toolkit for Automating Interactive Programs (O'Reilly) and SO but I cannot make expect_out(buffer) work with set, set env nor puts.

How can I put it in a variable for use in my bash script?

How can I parse a part of it (e.g. C00DE13988B4ABC93B43617C0FADAA8E1D4A0293 above) and put it in a variable for bash?

1

Since you're using expect with a here-doc in a bash script, you'd do:

output=$(
    expect << END
        expect script here
END
)

To reduce the output, add log_user 0 to the top of the expect body, and print the output of the GETINFO command

send -- "GETINFO circuit-status\r"
expect "250 OK\r"
puts $expect_out(buffer)

I mean this:

output=$(
    expect << EOD
        log_user 0
        spawn telnet localhost 9151
        expect "Escape character is '^]'."
        send -- "AUTHENTICATE $COOKIE\r"
        expect "250 OK\r"
        send -- "SIGNAL NEWNYM\r"
        expect "250 OK\r"
        send -- "GETINFO circuit-status\r"
        expect "250 OK\r"
        puts $expect_out(buffer)
        send -- "QUIT\r"
        expect eof
EOD
)
  • I don't follow, or you don't get my point. I need to send GETINFO in expect and put what comes after sending that command in a variable for later use in bash – 1.61803 Jun 17 '14 at 21:53
  • That's what I am attempting to help you with. I just didn't spoonfeed you the solution. How have I confused you? – glenn jackman Jun 17 '14 at 23:09
  • I already use var A for the expect script, and another var B to cut a string out of var A's output (no need to use puts as in your suggestion). I want to get rid of both vars, run expect in bash and return only GETINFO's value to some expect's default var that I can use directly in bash, if possible. – 1.61803 Jun 18 '14 at 17:28
  • have you tried my suggestions? – glenn jackman Jun 18 '14 at 17:41
  • I already had in place your first suggestion like this NEW_CIRCUIT=$(expect << EOD send -- "GETINFO circuit-status\r" expect "250 OK\r" EOD) EXIT_NODE_FP=$(echo $NEW_CIRCUIT | cut ) but, again, I want to get rid of $NEW_CIRCUIT and $EXIT_NODE_FP like I explained – 1.61803 Jun 18 '14 at 18:29
0

You could build a wrapper in bash, redirect the output of expect to a file, parse the file and set variables. Or variations thereof.

mark5:~/test# cat test.xp
send "bla\n"
mark5:~/test# expect test.xp
bla
mark5:~/test# expect test.xp > test.out
mark5:~/test# cat test.out
bla
mark5:~/test# #now parse test.out
  • And how do you redirect the output of expect to a file? That said, I want to do it from expect to bash. – 1.61803 Feb 9 '14 at 23:04
  • See my edit... Why would you not be able to redirect? Create a shell script that runs expect test.xp > test.out and parse what's in test.out after that – Marki Feb 9 '14 at 23:12
  • Oh I thought you were referring to redirecting here document I posted above. Wrapping is cumbersome. I'd prefer to handle expect's output directly as the sources mentioned state, although I couldn't figure it out. – 1.61803 Feb 10 '14 at 15:15
0

Too late I learned (Access variable from expect script in bash script) that environment vars from a child cannot be passed to the parent's environment, at least the way I described, i.e., referring to an expect default var from bash shell. So I'll just keep on using the expect script in a var and parse its value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.