📄 logview.tk
字号:
#!/usr/bin/wish -f# logView.tk --# # Essentially a general purpose GUI wrapper to tail, gui and any commands# that will output data continuosly. This GUI has the ability to record# the commands as smart buttons, so that you can re-run the same commands# again and again without having to retype set tailRc "~/.tailrc"wm title . "Process Log Viewer"wm iconname . "Log Viewer"global tailSize textw fileName tailFd curNick tailOpts statusImgWin# tailSize --> size in lines of tail output to display# fileName --> File name: variable# tailFd --> proc fd or file fd of current tail process# curNick --> current nick being shown; nick essentially a shortcut to a cmd.# tailOpts --> saved options# statusImgWin --> window showing what kind of error it is!set tailSize 20set fileName "/home/"; #include your own path here# file types for the file selection dialog box.set tailOpts(types) { {"All files" *} {"Text files" {.txt .doc} } {"Text files" {} TEXT} {"Tcl Scripts" {.tcl} TEXT} {"C Source Files" {.c .h} } {"All Source Files" {.tcl .c .h} } {"Image Files" {.gif} } {"Image Files" {.jpeg .jpg} } {"Image Files" "" {GIFF JPEG}}}set tailOpts(wins) {}# Next, we will build the user interface. proc BuildTailGui {w} { global tailSize textw fileName tailFd curNick tailOpts statusImgWin global viewOptMenu if {$w == "."} { set w ""; } # Build Menu for file menu $w.menu -tearoff 0 # File menu set m $w.menu.file menu $m -tearoff 0 $w.menu add cascade -label "File" -menu $m -underline 0 $m add command -label "Add New ..." -command {AddNew} -underline 0 $m add command -label "Exit" -command {exit} -underline 0 # Edit Menu set m $w.menu.edit menu $m -tearoff 0 $w.menu add cascade -label "Edit" -menu $m -underline 0 $m add command -label "Delete Nicks.." -command {DeleteNicks} -underline 0 # Help Menu set m $w.menu.help menu $m -tearoff 0 $w.menu add cascade -label "Help" -menu $m -underline 0 $m add command -label "About..." -underline 0 -command { tk_messageBox -parent . -title "Process Log Viewer" -type \ ok -message "Tk Tail Tool \nby Krishna Vedati(kvedati@yahoo.com)" } # The routine then adds a text widget to display the output of any log proces.# Next, the routine builds rows of widgets. # Create status/error message window frame $w.status -relief sunken -bd 2 set statusImgWin [label $w.status.flag -bitmap info] label $w.status.lab -textvariable statusText -anchor w -bg "wheat" pack $w.status.flag -side left pack $w.status.lab -side left -fill both -expand 1 # File name: entry panel frame $w.file label $w.file.label -text "File name:" -width 13 -anchor w entry $w.file.entry -width 30 -textvariable fileName button $w.file.choose -text "..." -command \ "set fileName \[tk_getOpenFile -filetypes \$tailOpts(types) \ -parent \[winfo toplevel $w.file\]\];" button $w.file.button -text "Tail File" \ -command "AddToView file \$fileName" pack $w.file.label $w.file.entry -side left pack $w.file.choose -side left -pady 5 -padx 10 pack $w.file.button -side left -pady 5 -padx 10 bind $w.file.entry <Return> " AddToView file \$fileName" focus $w.file.entry # Command entry panel frame $w.fileC label $w.fileC.cLabel -text "Command:" -width 13 -anchor w entry $w.fileC.cEntry -width 40 -textvariable command label $w.fileC.nLabel -text "Nick:" -anchor w entry $w.fileC.nEntry -width 15 -textvariable nick button $w.fileC.add -text "Add" -command "AddToView \"command\"\ \$command \$nick;" pack $w.fileC.cLabel $w.fileC.cEntry -side left pack $w.fileC.nLabel -side left -pady 5 -padx 10 pack $w.fileC.nEntry -side left -pady 5 -padx 5 pack $w.fileC.add -side left -pady 5 -padx 5 # Option Menu command panel frame $w.optF label $w.optF.label -text "View:" -width 12 -anchor w set viewOptMenu [tk_optionMenu $w.optF.optB curNick " "] button $w.optF.stop -text "Stop" -command Stop pack $w.optF.label -side left pack $w.optF.optB -side left -pady 5 pack $w.optF.stop -side left -pady 5 # create text widget frame $w.textf -bg red text $w.textf.text -height [expr $tailSize] -xscrollcommand "$w.textf.scrollh set" \ -yscrollcommand "$w.textf.scrollv set" -bg lightblue set textw $w.textf.text scrollbar $w.textf.scrollh -orient horizontal -command "$w.textf.text xview" scrollbar $w.textf.scrollv -orient vertical -command "$w.textf.text yview" pack $w.textf.scrollv -side right -fill y -expand 1 pack $w.textf.scrollh -side bottom -fill x -expand 1 pack $w.textf.text -fill x -fill y -expand 1 # pack all the frames [winfo toplevel $w.textf] configure -menu $w.menu pack $w.status -side bottom -fill x -pady 2m pack $w.file -side top -fill x -expand 1 pack $w.fileC -side top -fill x -expand 1 pack $w.optF -side top -fill x -expand 1 pack $w.textf -side top -fill x -fill y -expand 1}# Once the user sets up a command or a file-type nick, the TailFile method will get called.# This method makes sure that the specified file exists.# It creates the command and opens it as a process.# Then, it binds a read event to the file descriptor and returns.# The read event will call TailUpdate every time the file identifier associated# with the process is readable.# TailFile --# # Show the tail of the request file.## Arguments:# file name to be tailed.# # Results:# The tail of the file is shown in the window.#proc TailFile { type file {nick ""}} { global tailSize tailFd textw curNick set w $textw catch { fileevent $tailFd readable {} close $tailFd update } $w delete 1.0 end if {$type == ""} { $w insert end "Illegal type..."; return } if {$type == "file"} { if {$file == ""} { $w insert end "please specify a valid filename..." return } if ![file exists $file] { DeleteFromView $file $w insert end "file $file does not exist..." return } set nick $file } elseif {$type == "command"} { if {$file == ""} { $w insert end "please specify a command..." return } } if {$type == "file"} { set tailFd [open "|tail -f $file" r] wm title [winfo toplevel $w] "Tail tool \[tail -f $file\]" } elseif {$type == "command"} { if [catch {set tailFd [open "|$file" r]}] { SetStatus error "can't execute command $file..." DeleteFromView $nick set curNick "" return } wm title [winfo toplevel $w] "Tail tool \[tail |$file\]" } fconfigure $tailFd -blocking 0 set lines 0 fileevent $tailFd readable "TailUpdate \$tailFd"}# The TailUpdate procedure gets called as part of the event handler on the current log process read status.# When this procedure gets called, it collects the output from the process and inserts it into the text widget.# It also makes sure that at any given time, no more than $tailSize lines are shown in the text window.proc TailUpdate {fileFd} { global textw curNick global tailSize tailFd set w $textw if [eof $tailFd] { fileevent $tailFd readable {} $w insert end "Tailing \"$curNick\" done..." return } set line [gets $tailFd] $w insert end $line $w insert end "\n" set lines [lindex [split [$w index end] .] 0] if {$lines == [expr $tailSize+1]} { $w delete 1.0 2.0 } $w yview moveto 1.0}# The Stop call-back is used to stop the current logProcess.# Stop the current tailing process.proc Stop {} { global tailFd set pid [pid $tailFd] catch {exec kill -9 $pid}}# The AddNew procedure gets called every time the user adds a new shortcut.# It creates a simple GUI for the user to create a new command nick.# AddNew --# Add a new tail file to the system## Arguments:# none.# # Results:# proc AddNew {args} { toplevel .addnew set w .addnew wm title $w "Add new tail file..." frame $w.top frame $w.sep -bd 2 -relief ridge frame $w.bot set k $w.top label $k.name -text "Nickname for item:" label $k.command -text "Command:" grid $k.name -row 0 -column 0 -sticky e grid $k.command -row 1 -column 0 -sticky e entry $k.nameE -textvariable nameE -width 40 entry $k.commandE -textvariable commandE -width 50 grid $k.nameE -row 0 -column 1 -sticky ew grid $k.commandE -row 1 -column 1 -sticky ew grid columnconfigure $k 1 -weight 1 grid propagate $k 1 pack $w.top -side top -fill both -expand 1 pack $w.sep -side top -fill x -expand 1 -pady 5 pack $w.bot -side top -fill x -expand 1 button $w.bot.apply -text "Add" -command "AddToView \"command\" \"\$commandE\" \"\$nameE\"" button $w.bot.dismiss -text "Dismiss" -command {destroy .addnew} pack $w.bot.apply $w.bot.dismiss -side left -expand 1 PositionWindow $w}# The SetStatus procedure is used to set GUI status messages in the status window.# It's a general-purpose routine to display both error and informational messages.# If a type error occurs, then an error bitmap will be displayed in the status window.proc SetStatus {type text {timer 5000}} { global statusText statusImgWin set statusText $text after $timer "set statusText \"\"" $statusImgWin config -bitmap $type after $timer "$statusImgWin config -bitmap \"\""}# The AddToView command will add a nick to the option button.# Before it adds the item to the option menu, it makes sure that the user had supplied# the required information.proc AddToView {type command {nick ""}} { global tailOpts viewOptMenu catch {Stop} if {$type == "file"} { set nick $command if {$command == ""} { SetStatus error "Please supply File name..." } } elseif {$type == "command"} { if {($nick == "") || ($command == "") } { SetStatus error "Please supply both nick and command names..." return } } set l [list "$type" "$nick" "$command"] if ![info exists tailOpts(wins)] { set tailOpts $l return } else { foreach item $tailOpts(wins) { if {$nick == [lindex $item 1]} { if {$type == "file"} { SetStatus info "File $nick is all ready in the tail list...." } else { SetStatus info "Nick $nick is all ready in the tail list...." } return; } } lappend tailOpts(wins) $l } UpdateOptionMenu $viewOptMenu invoke end}# The DeleteNicks routine will create a simple listbox-based user interface for the user to delete the nicks.proc DeleteNicks {} { global tailOpts if ![info exists tailOpts(wins)] { SetStatus info "No entries to delete..." return; } if {$tailOpts(wins) == {}} { SetStatus info "No entries to delete..." return; } catch {destroy .delent} toplevel .delent set w .delent wm title $w "Delete Entry" scrollbar $w.h -orient horizontal -command "$w.list xview" scrollbar $w.v -orient vertical -command "$w.list yview" listbox $w.l -selectmode single -width 20 -height 10 \ -setgrid 1 -xscroll "$w.h set" -yscroll "$w.v set" frame $w.buts button $w.buts.d -text "Delete" -command { set index [.delent.l curselection ]; if {$index == ""} {return} set sel [.delent.l get $index ]; puts "sel $sel ; index $index" DeleteFromView $sel; .delent.l delete $index } button $w.buts.dismiss -text "Dismiss" -command "destroy $w" grid $w.l -row 0 -column 0 -columnspan 2 -sticky "news" grid $w.v -row 0 -column 2 -sticky "ns" grid $w.h -row 1 -column 0 -columnspan 2 -sticky "we" grid $w.buts -row 2 -column 0 -columnspan 3 pack $w.buts.d $w.buts.dismiss -side left -padx 10 foreach ent $tailOpts(wins) { $w.l insert end [lindex $ent 1] } PositionWindow $w} # The DeleteFromView routine is an internal routine that removes the specified nick from the data structures# and updates the optionbutton.proc DeleteFromView {nick} { global tailOpts if {$nick == ""} { return } set newList {} if ![info exists tailOpts(wins)] { return } foreach item $tailOpts(wins) { if {$nick != [lindex $item 1]} { lappend newList $item } } set tailOpts(wins) $newList UpdateOptionMenu}# The PositionWindow routine centers a toplevel dialogue box around its parent.# It is used to map dialog boxes on the main window, instead of some far-away corner of the screen.## PositionWindow --# # Position the toplevel window centered to its parent.## Arguments:# toplevel window.# # Results:# Positions the window #proc PositionWindow {w} { set paren [winfo parent $w] wm iconify $w set parenConf [wm geometry $paren] set parenConf [split $parenConf {+ - x}] set winConf [split [wm geometry $w] {+ - x}] set X [expr [lindex $parenConf 2] + [lindex $parenConf 0]/2 - \ [winfo reqwidth $w]/2] set Y [expr [lindex $parenConf 3] + [lindex $parenConf 1]/2 - \ [winfo reqheigh $w]/2] wm geometry $w +$X+$Y wm deiconify $w}# The UpdateOptionMenu command updates the nicks option menu widget.# UpdateOptionMenu --#### Arguments:### Results:#proc UpdateOptionMenu {} { global tailOpts curNick viewOptMenu $viewOptMenu delete 0 end if ![info exists tailOpts(wins)] { return } if {$tailOpts(wins) == {}} { set curNick "" return } foreach item $tailOpts(wins) { $viewOptMenu add command -label [lindex $item 1] -command "catch Stop; TailFile \"[lindex $item 0]\" \"[lindex $item 2]\" \"[lindex $item 1]\" " set curNick [lindex $item 1] }}# Finally, we map the main window.wm withdraw .toplevel .tBuildTailGui .t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -