My problem is this, I have created an Expect script that logs into a
switch and configures it. It prompts the user for 3 pieces of
information and then it goes off on its merry way, works wonderfully.
Now, in a moment of daring, I started looking at Tcl/Tk to wrap this
script of mine up in a more user friendly GUI, as the script currently
runs from a command line. Mind you, this is going to be a very
simplistic looking GUI (at least at first, as my knowledge grows, so
too will the complexity I would assume). The function of this GUI is
to replace part of the Expect script that prompts the user for those 3
pieces of information.
So this leads me to my question(s)
1) Is it possible to take the input from this GUI and define it as an
arg to the Expect script
2) I would like to have the "Configure" button execute Expect script
(with the args defined based on the user input in the lines above).
However when I use the "exec" command, it appears to hang, and I am
forced to kill the process. Feels like I'm making a newb mistake on
this one, but as a newb, it is difficult to spot it.
3) Would it be possible to put a progress bar into this Tk script, so
that after the "Configure" button is pressed, the user is presented
with a time of completion estimate (and yes, I come from a Windows
background)
4) Speaking of Windows backgrounds, my final question is this: Would
it possible to port this program to a Windows environment from my
current Linux environment. I have read a little about "Starkits/packs"
and this seems like the route to go, but may be slightly above my
means at this time.
5) And this is the real bit of noobishness I'm sure, but here goes:
whatever the user enters in one prompt, appears in both of the other
entry boxes. I'm gonna go ahead and hazard a guess that this is
because I'm doing it wrong.
Below is a sample of my Tcl/Tk GUI script (be gentle, I know its a
hack :)
wm title . "DumDum"
#first prompt
label .a -text "GENERIC USER PROMPT NUMBER 1"
#first entry box
entry .b -width 40 -relief sunken -bd 2 -textvariable name
focus .b
#second prompt
label .c -text "GENERIC USER PROMPT NUMBER 2"
#second entry box
entry .d -width 40 -relief sunken -bd 2 -textvariable name
focus .d
#third prompt
label .e -text "GENERIC USER PROMPT NUMBER 3"
#third entry box
entry .f -width 40 -relief sunken -bd 2 -textvariable name
focus .f
#buttons
set text Enter
proc doIt {widget} {
global text
if {$text == "Enter"} {exec *EXPECTSCRIPTHERE*
} else {
set text "Enter"
}
$widget configure -text $text
}
button .b1 -text "Enter" \
-command "doIt .b1"
button .b2 -text "Quit" \
-command "destroy ."
#gridding instruction
grid .a -row 0 -column 0 -sticky e
grid .b -row 0 -column 1 -sticky w
grid .c -row 1 -column 0 -sticky e
grid .d -row 1 -column 1 -sticky w
grid .e -row 2 -column 0 -sticky e
grid .f -row 2 -column 1 -sticky w
grid .b1 -row 3 -column 0 -columnspan 2
grid .b2 -row 3 -column 1 -columnspan 2
*NAMES AND TEXT EDITED AS IRRELEVANT*
Please note, I'm not looking for someone to write this for me, just
sort of looking for a good place to get started (and so help me, the
first person that types "www.google.com"...lol)
And don't hesitate to throw in a "Your inferior code is inferior" if
this is simply too newb.
Thanks in advance for your help, and let me know if theres any more
info I can provide, and I shall do so to the best of my ability.
-Dukie91191
Yes, but might even be easier to merge the GUI and expect script,
after all Expect is just one package require away...
> 2) I would like to have the "Configure" button execute Expect script
> (with the args defined based on the user input in the lines above).
> However when I use the "exec" command, it appears to hang, and I am
> forced to kill the process. Feels like I'm making a newb mistake on
> this one, but as a newb, it is difficult to spot it.
exec waits till the script finishes and blocks the gui...
> 3) Would it be possible to put a progress bar into this Tk script, so
> that after the "Configure" button is pressed, the user is presented
> with a time of completion estimate (and yes, I come from a Windows
> background)
yes
> 4) Speaking of Windows backgrounds, my final question is this: Would
> it possible to port this program to a Windows environment from my
> current Linux environment. I have read a little about "Starkits/packs"
> and this seems like the route to go, but may be slightly above my
> means at this time.
Depends on what Expect Features you use, not all of expects goodies
work on Windows.
> 5) And this is the real bit of noobishness I'm sure, but here goes:
> whatever the user enters in one prompt, appears in both of the other
> entry boxes. I'm gonna go ahead and hazard a guess that this is
> because I'm doing it wrong.
Yes. Look at the name you give as -textvariable thats the name of a
global variable that takes the result.
Basically try to start from something like this:
package require Tk 8.5
package require Expect
array set CONFIG {setting1 default1
setting2 default2
setting3 default3
}
proc increment_progress {} {
incr ::progress
# refresh the GUI, not the best possible style, even a bit
dangerous
# but works for simple guis
update
}
proc start_it {} {
global CONFIG
set ::argv [list $CONFIG(setting1) $CONFIG(setting2)
$CONFIG(setting3)]
set ::argc [llength $::argv]
source "your_expect_script"
}
proc gui {} {
global CONFIG
ttk::label .a -text "Some label"
ttk::entry .a_entry -textvariable CONFIG(setting1)
ttk::label .b -text "Some other label"
ttk::entry .b_entry -textvariable CONFIG(setting2)
ttk::label .c -text "Some third label"
ttk::entry .c -textvariable CONFIG(setting3)
ttk::button .start -text "Start" -command {start_it}
ttk::button .quit -text "Quit" -command { destroy .}
set ::progress 0
ttk::progressbar .prog -variable progress -maximum 100 -orient
horizontal
grid .a .a_entry -sticky w
grid .b .b_entry -sticky w
grid .c .c_entry -sticky w
grid .prog -sticky ew -columnspan 2
grid .start .quite
}
vwait forever
Now you just call increment_progress in your expect script whenever
progress is made, if it reaches 100 the progress bar is full, refine
as needed...
Michael
expect is an extension to tcl
tk is an extension to tcl
You can use both at the same time and from the same script.
[exec]ing your expect script will make the gui inresponsive
while it is running.
label .lh -text Host:
entry .eh -textvariable ::IP
set ::IP ""
label .lu -text User:
entry .eu -textvariable ::USR
set ::USR ""
label .lp -text Pass:
entry .ep -textvariable ::PASSWD
set ::PASSWD ""
button .b -text Connect -command {ssh_connect $::IP $::USR}
label .ls -textvariable ::STATUS
pack -side left .lh .eh .lu .eu .lp .ep .b .ls
set ::STAT -/-
proc ssh_connect {ip usr} {
if {$ip == "" } {
set ::STAT NO_IP
return
}
if {$usr == "" } {
set ::STAT NO_USR
return
}
set ::status trying:$ip
spawn ssh ${usr}@$host
set :curr_spid $spawn_id
expect "assword: " {
set ::STAT "sending password"
exp_send "$::PASSWD\r"
...
}
vwait forever
#end
yes, certainly.
> 2) I would like to have the "Configure" button execute Expect script
> (with the args defined based on the user input in the lines above).
> However when I use the "exec" command, it appears to hang, and I am
> forced to kill the process. Feels like I'm making a newb mistake on
> this one, but as a newb, it is difficult to spot it.
> 3) Would it be possible to put a progress bar into this Tk script, so
> that after the "Configure" button is pressed, the user is presented
> with a time of completion estimate (and yes, I come from a Windows
> background)
Do you know how long your expect script runs? Are there predictable
"signposts" that it outputs along the way?
> 4) Speaking of Windows backgrounds, my final question is this: Would
> it possible to port this program to a Windows environment from my
> current Linux environment. I have read a little about "Starkits/packs"
> and this seems like the route to go, but may be slightly above my
> means at this time.
Can your expect script run from Windows? What external processes does
it spawn?
> 5) And this is the real bit of noobishness I'm sure, but here goes:
> whatever the user enters in one prompt, appears in both of the other
> entry boxes. I'm gonna go ahead and hazard a guess that this is
> because I'm doing it wrong.
You're using the same variable name for each of your entry widgets.
> wm title . "DumDum"
> #first prompt
> label .a -text "GENERIC USER PROMPT NUMBER 1"
> #first entry box
> entry .b -width 40 -relief sunken -bd 2 -textvariable name
use: -textvarialbe name1
> focus .b
> #second prompt
> label .c -text "GENERIC USER PROMPT NUMBER 2"
> #second entry box
> entry .d -width 40 -relief sunken -bd 2 -textvariable name
use: -textvarialbe name2
> focus .d
> #third prompt
> label .e -text "GENERIC USER PROMPT NUMBER 3"
> #third entry box
> entry .f -width 40 -relief sunken -bd 2 -textvariable name
use: -textvarialbe name3
> focus .f
> #buttons
> set text Enter
> proc doIt {widget} {
> global text
> if {$text == "Enter"} {exec *EXPECTSCRIPTHERE*
exec /path/to/expect/script $name1 $name2 $name3 &
If you didn't care about when it ends, the "&" launches the process in
the background.
But, you do (you want a progress bar), so you'll want to launch your
expect script like this:
set pipe [open "| expect_script $name1 $name2 $name3" r]
fconfigure $pipe -buffering line
fileevent $pipe readable [list handle $pipe]
#...
proc handle {pipe} {
if {[gets $pipe line] == -1} {
if {[eof $pipe]} {
# expect script is finished, tidy up
close $pipe
fileevent $pipe readable {}
# do something with your progress bar, and perhaps raise
# a dialog box to notify the user
} else {
# should not happen, did not read a whole line
}
} else {
# do something with this line of output from your expect
# script, such as calculating the time remaining, and set a
# progress variable
}
}
If you want to invest more time in your GUI, the BWidget package
contains a ProgressBar widget.
http://tcllib.sourceforge.net/BWman/contents.html
--
Glenn Jackman
Write a wise saying and your name will live forever. -- Anonymous
Thank you for your responses Glenn,
To answer some of your questions,
> Do you know how long your expect script runs? Are there predictable
> "signposts" that it outputs along the way?
There are definite "signpost" events during the running of this
script, and it takes more or less the same time each time it is run.
It must unconfigure, reboot (wait), and then add values near the end.
> Can your expect script run from Windows? What external processes does
> it spawn?
Currently it spawns "Minicom" as the outer process. However, if I were
to port to windows, I could have it spawn terra term or something like
that.
> exec /path/to/expect/script $name1 $name2 $name3 &
As far as this command goes (starting small first, just want to see
this whole thing happen, then worry about making it prettier)
when I put this in, I should edit the expect file so that there is no
user prompt for variables, as (by my understanding at any rate) this
command defines
$name1 $name2 $name3
to the Expect script, inserting them appropriately.
Please correct me if I'm wrong here.
Best Regards,
Dukie91191
> exec /path/to/expect/script $name1 $name2 $name3 &
did not do it
So I took out the & and was given an error
Error: can't read "name1": no such variable
Would this mean that -textvariable is not storing input or something?
Also, in that format, what I mean to say above is $name1 $name2 $name3
are defined TO Expect via that command.
Bruce
I'd recommend getting familiar with ssh. ssh clients exist for
(probably) all platforms.
> > exec /path/to/expect/script $name1 $name2 $name3 &
>
> As far as this command goes (starting small first, just want to see
> this whole thing happen, then worry about making it prettier)
> when I put this in, I should edit the expect file so that there is no
> user prompt for variables, as (by my understanding at any rate) this
> command defines
> $name1 $name2 $name3
> to the Expect script, inserting them appropriately.
Indeed. Your expect script will receive those values in the global list
$argv
Alright, this is (I think) my final newb question.
So far, thanks to the responses here, I have gotten to Tcl/Tk program
to successfully execute my Expect command. However, Expect cannot find
the variables defined by the users input into the Tk program and
returns "cannot find variable name1: no such variable". My question
is, how do I edit the script so that the variables defined by the
users input into the Tk program are seen by expect and acted upon.
Thank you again for all your help.
-Dukie91191
Your expect script cannot know about variable names used in your tk
script (being a different process and all)
Put this in your expect script (near the beginning)
set name1 [lindex $argv 0]
set name2 [lindex $argv 1]
set name3 [lindex $argv 2]
Or, use this idiom for Tcl 8.4:
foreach {name1 name2 name3} $argv break
New development:
After digging about for a bit, I've stumbled upon Expectk (remember
earlier when I said I was new to this stuff? I wasn't lying). It does
exactly what I ask of it, which is a big bonus for me. Variable are
still a bit of a spot, but I might be able to sort it on my own from
here.
*OFF TOPIC*
Would anyone have any suggestion for good dead-tree readings on Tcl/Tk/
Expect? Out of all other languages this one has really caught my eye,
and I'd very much like to master it. Any suggestions would be
appreciated.
and that is a bit old, in recent (like 5 years?) rel;eases expect is
just a simple package that can be added so you can combine expect, tk
and any other useful tcl packages all in one interpreter without needing
custom binary builds like expectk
>
> *OFF TOPIC*
> Would anyone have any suggestion for good dead-tree readings on Tcl/Tk/
> Expect? Out of all other languages this one has really caught my eye,
> and I'd very much like to master it. Any suggestions would be
> appreciated.
*the* book is "Exploring Expect" by the author of expect.
for Tcl stuff get the latest release of "Practical Programming in Tcl/Tk"
see also <http:wiki.tcl.tk/book> for more complete listings.
Bruce
is equivalent to running wish and then doing a
package require expect
inside the sscript
or running expect and then doing a
package require Tk
inside the script
or running tclsh and doing a
package require Tk
package require expect
inside the script.
>
> *OFF TOPIC*
> Would anyone have any suggestion for good dead-tree readings on Tcl/Tk/
> Expect? Out of all other languages this one has really caught my eye,
> and I'd very much like to master it. Any suggestions would be
> appreciated.
"exploring expect" ( written by the author of expect) is good reading
on both tcl and expect.
"Tcl and Tk" by Brent Welch is a book you can hit most tcl problems over the head
with. literaly as well as figuratively.
The Tclers Wiki
http://wiki.tcl.tk
is a fount of help ideas and codesnippets well worth perusing.
uwe
tcltutor http://www.msen.com/~clif/TclTutor.html is another fun way of
learning tcl commands without dead trees.
yahalom
I have one last (I think) question.
When I define variables from
entry with the -textvariable tag, I assume (first mistake?) that those
variable are put on the global list. However, at the beginning of my
proc, i have added a global declaration
(e.g.
global name1
global name2
global name3
etc...)
But when the script (Expect script, which is now contained within the
tcl file {Expect script is no longer spawned as a separate process})
is started within the proc, it stops and does not enter the values for
those global variables. This is odd, because before, I received a
"variable does not exist" error which halted the script. Now it looks
like it is simply waiting, as if the variable is defined, but contains
no value.
I was hoping to solve this one on my own, but I know when I am beaten.
Any ideas on this are most appreciated.
Thank you in advance (again)
-Dukie91191
EDIT:
Problem solved. Ended up being an error in the Expect portion, works
wonderfully now.
Thanks to all who have helped!
You have at least one entry that uses a -textvariable. Its
named textvariable is indeed in global scope, I assure you.
You have written that "when the script ... is started within
the proc, it stops and does not enter the values for those
global variables." I don't know what that means. A [proc]
is starting a script--are you referring to something like
proc a {} {
source the_script.tcl
...
}
? You write that something "does not enter the values for
those global variables." Do you have code intended to enter
values for global variables? I hadn't noticed that ...
I strongly urge you to reduce your mysteries to minimal
pieces of specific code that others of us can understand;
that's often the best way to set yourself up to receive help.
Here's an interactive session:
$ tclsh
% global x
% set x
can't read "x": no such variable
% exit
Is that pertinent to your situation? In casual language, Tcl
variables can have a scope even before receiving (being bound
to, ...) a value. Is that what you have in mind?