Reputation: 29
# Prints the string in a file
puts $chan stderr "$timestamp - Running test: $test"
# Prints the string on a console
puts "$timestamp - Running test: $test"
Is there a way I can send the output of puts to the screen and to a log file at the same time? Currently I have both the above two lines one after the other in my script to achieve this.
Or is there any other solution in tcl ?
Upvotes: 1
Views: 4131
Reputation: 13252
This isn't something I've used extensively, but it seems to work (Tcl 8.6+ only):
You need the channel transform tcl::transform::observe
package:
package require tcl::transform::observe
Open a log file for writing and set buffering to none:
set f [open log.txt w]
chan configure $f -buffering none
Register stdout
as a receiver:
set c [::tcl::transform::observe $f stdout {}]
Anything written to the channel $c
will now go to both the log file and stdout
.
puts $c foobar
Note that it would seem to make more sense to have the channel transformation on top of stdout
, with the channel to the log file as receiver, but I haven't been able to make that work.
Documentation: chan, open, package, puts, set, tcl::transform::observe (package)
Upvotes: 3
Reputation: 32484
Use the following proc instead of puts
:
proc multiputs {args} {
if { [llength $args] == 0 } {
error "Usage: multiputs ?channel ...? string"
} elseif { [llength $args] == 1 } {
set channels stdout
} else {
set channels [lrange $args 0 end-1]
}
set str [lindex $args end]
foreach ch $channels {
puts $ch $str
}
}
Examples:
# print on stdout only
multiputs "1"
# print on stderr only
multiputs stderr "2"
set brieflog [open brief.log w]
set fulllog [open detailed.log w]
# print on stdout and in the log files
multiputs stdout $brieflog $fulllog "3"
Upvotes: 3