Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Curious setting variable problem

Status
Not open for further replies.

IllegalOperation38

Technical User
Jun 13, 2003
9
0
0
US
I can do this Linux command from TCL

set USER_NAME [exec id -nu]

puts $USER_NAME

IllegalOperation

But when I do a

set SERVER_STATUS [exec /etc/rc.d/init.d/vsftpd status]

I get

vsftpd is stopped
child process exited abnormally




The "vsftpd is stopped" is what I want, but the "child process exited abnormally" is what I want to lose, nor does the variable get set either due to this problem.


I can issue this same command from the BASH shell and get the desired results without the error.

bash> /etc/rc.d/init.d/vsftpd status

vsftpd is stopped

But from TCL this doesnt want to work for some reason.


Can anyone clue me in?
 
I tested your commands under RedHat 9 / Tcl 8.3 / vsftpd-1.1.3-8 and had no errors. Maybe there is something wrong with your installation?
Alternative way to determine the username:
Code:
set USER_NAME $::tcl_platform(user)
to make sure a unix command is executed in a bash context,
consider
Code:
set SERVER_STATUS [exec bash -c "/etc/init.d/vsftpd status"]
HTH

Tobias



T. Gabele
Bierwirth & Gabele GBR
 
Hmmmm this is an oddity. I am running the same exact specs.



I have another computer with Redhat 9.0, I just moved to it and tried the same command. Here are the results step by step. Perhaps I am not doing something right?


______________________________________________________________

[illegal@localhost illegal]$ tclsh
% [exec /etc/rc.d/init.d/vsftpd status]
vsftpd is stopped
child process exited abnormally
%

% set SERVER_STATUS [exec /etc/rc.d/init.d/vsftpd status]
vsftpd is stopped
child process exited abnormally
% puts $SERVER_STATUS
can't read "SERVER_STATUS": no such variable
%



 
This problem was solved by doing this


set f [open "|/etc/rc.d/init.d/vsftpd status 2>/dev/null" r]
set x [read $f]
close $f



Thanks for your time
 
Yes, this is a somewhat unfortunate feature of Tcl's exec command. If the program executed has a non-zero exit code, the exec command tacks on that "child process exited abnormally" message to whatever standard output it collected from the program, and raises an error condition. I've looked, but there appears to be no way to prevent exec from appending that message. Of course, you could just strip it off "manually" in situations like this.

You also discovered another way of handling the situation by using a pipeline, which is fine. Just be aware that when using process pipelines in Tcl, the close command raises an error if: 1) it detects that a program in the pipeline had a non-zero exit code; or 2) a program in the pipeline wrote to its [tt]stderr[/tt] channel, and you didn't explicity redirect [tt]stderr[/tt] in your pipeline specification. So, you should always use catch when closing a pipeline channel to guard against those situations.

Here's an example from an interactive session where I opened a pipeline to a Tcl script called error2.tcl, which writes "I'm exiting abnormally" to its [tt]stdout[/tt] channel, then exits with a non-zero exit code:

[tt]% [ignore]set fid [open "| tclsh error2.tcl"][/ignore]
file9f8220
% [ignore]set output [read $fid][/ignore]
I'm exiting abnormally

% catch {close $fid} ret; # Note that close raises an error
1
% puts $ret; # Here's the error message
child process exited abnormally[/tt]

- Ken Jones, President, ken@avia-training.com
Avia Training and Consulting, 866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Ken,


I have been following your advice in this forum for a long time and have learned alot from you. Thanks for the clarification.


Perhaps you can assist me in this continued request.

I have written a piece of code that will show the status of my VSFTPD server, wether it is online or not. But the problem is it will only query one time, when I exec the proc I made. I need it to query often and constant, like every few seconds, to alert my program that the daemon status has changed.


I am not quite sure how to construct a loop that will perform this action I seek, but the code I have so far is something like this



proc status {} {
global not_online is_online
frame .bottom
pack .bottom -fill x
set display [text .bottom.main -relief sunken -background black -foreground green -height 1 -width 20]
pack .bottom.main
set f [open "|/etc/rc.d/init.d/vsftpd status" r]
set x [read $f]
set offline [string length $x]
if {$offline == "18"} {
$display insert 1.0 $not_online
} else {
$display insert 1.0 $is_online

}
}


status
______________________________________________________


In this code, when I exec status I get a small text frame telling me the status, but I need to keep the status current.


Thank you for your ideas or anyone else that may help me.
 
Hi,
i would suggest splitting gui and statusupdate in two procs. The status_update proc calls itself after every 5 seconds

Code:
set message(offline) "down :-("
set message(online)  "up! :-)"
set ftpstatustext "not determined"

proc status_gui {} {
 catch {destroy .bottom}
 frame .bottom
 pack .bottom -fill x
 set display [label .bottom.main -relief sunken  -background  black  -foreground green -width 20  -textvariable ::ftpstatustext] 
  pack $display
status_update $display
}


proc status_update {d} {
global ftpstatus
# if the display widget doesnt exist, recreate it
if {![winfo exists $d]} {
return [status_gui]
}
set f [open "|/etc/rc.d/init.d/vsftpd status 2>/dev/null" r]
set x [read $f]
catch {close $f}
if {[string length $x] == 18} {
  set ftpstatustext $::message(offline)
  } else {
  set ftpstatustext $::message(online)
  }
# call the update every 5 secs
after 5000 [list status_update $d]
}

status_gui


regards,

Tobias



Tobias Gabele
Bierwirth & Gabele SoftwareDesign GBR
 
Quote:

after 5000 [list status_update $d]
}




Nice one Tobias, this set the bill perfectly and was a great learning curve as well.
 
Tobias's example pretty much demonstrated the approach I was going to recommend. The only potential improvement I'd suggest is in retrieving the information from the pipe. For an external program that finishes in less than a second or so, there shouldn't be a problem. But if it takes a while for the program to finish, the read command blocks until all output from the program is available (that is, it detects an EOF on the channel). For a GUI program, this means that your GUI is frozen, completely unresponsive to user input and unable to refresh the screen, until the read command returns and you get back to your event loop.

So, if the program you're running is going to take a while to complete, you'll want to use the fileevent command to set up a handler to read data as it becomes available and handle the data asynchronously. Some examples of this are shown on the Tcl'ers Wiki ( I'd suggest starting with the page "fileevent,"
- Ken Jones, President, ken@avia-training.com
Avia Training and Consulting, 866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top