A.在tk中要如何讓視窗,顯示執行linux的過程.
這是我在網路上看到的,稍微修改,只要套用這個程式,就能輕易達成
首先,先source
source ./add_run_frame.tk
呼叫add_run_frame程序,在.新開了text的frame視窗(.text),會在side top也就是緊貼.上方,寬80高10(是文字dpi,非screen dpi)
add_run_frame ".text" 80 10
呼叫Run程序執行Linux指令,結果會出現在frame .text的文字區
Run "echo $::file_pass | sudo -S update-grub"
3個步驟而已,夠簡單了吧!!
B.
add_run_frame.tk檔案
#!/usr/bin/wish
##########################新加一個frme,給一個Linux指令,會顯示在此frame,根據網路上資料修改##########################
proc add_run_frame { var x y } {
global log run_frame
set run_frame $var
frame $run_frame
#文字區
set log [text $run_frame.log -width $x -height $y \
-yscrollcommand {$run_frame.scroll set}]
#拉動滾軸加入文字區
scrollbar $run_frame.scroll -command {$run_frame.log yview}
#滾軸layout,右側充滿y
pack $run_frame.scroll -side right -fill y
#文字區,左側,填滿xy,並隨視窗擴充
pack $run_frame.log -side left -fill both -expand true
#frame填滿xy,並隨視窗擴充
#pack $run_frame -side top -fill both -expand true
pack $run_frame -side top
#place $run_frame -x 0 -y 0
}
#############################LOG RUN################################################################################
proc Run {command} {
global input log but
if [catch {open "|$command |& cat"} input] {
$log insert end $input\n
} else {
fileevent $input readable Log
$log insert end $command\n
#$but config -text Stop -command Stop
}
}
proc Log {} {
global input log
if [eof $input] {
Stop
} else {
gets $input line
$log insert end $line\n
$log see end
}
}
# Stop the program and fix up the button
proc Stop {} {
global input but
catch {close $input}
#$but config -text "Run it" -command Run
}
C.
來一個GRUB2實際例子,我每次要更改多重開機的圖片,和文字顏色,都要去修改/boot/grub/grub.cfg很麻煩,就用tcl/tk加上bash shell寫了一個視窗工具程式,
要更改grub設定檔,當然需要root才行.
首先會要讓使用者輸入root密碼,可能你會覺得奇怪,我怎可能知道每個人的root password,去判斷是否輸入正確,是的你猜對了,我是不可能知道的,那我要如何判斷,套用古人說的:山不轉,路轉,路不轉,人轉.
原理很簡單,根據使用者輸入密碼,執行sudo ls,然後存到/tmp/log_pass,若不是空字串,代表使用者輸入root password正確,如下
exec echo $::file_pass | sudo -S ls > /tmp/log_pass
本程式,可能你會覺得寫得很複雜,其實原理很簡單,只是把相關grub設定檔,用sed,awk去處理,然後UPDATE GRUB,和一些tk ui設計而已,來看看結果吧.
所有使用的程式:
run_grub
#!/usr/bin/wish
##########################################################################################
# 作者:Y.P.LIN
# 用途:設定GRUB2的工具
# 程式:tcl/tk,bash sell
# 版權:GPL
# 用法:改執行權限chmod ./run_grub 執行./run_grub
# 備註:請先備份/boot/grub/grub.cfg
##########################################################################################
#package require Thread 2.1
#foreground,background本體,背景
source ./screen.tk
#source第二個frame
source ./grub.tk
#取消sudo
exec sudo -K
#####################改成USER可執行權限##################################
exec chmod u+x ./screen.tk
exec chmod u+x ./t.sh
exec chmod u+x ./grub.tk
exec chmod u+x ./screen.sh
exec chmod u+x ./add_run_frame.tk
########################source 螢幕中心點程序############################
#source ./screen.tk
########################form給輸入root密碼用##############################
wm title . "需要root"
#指定窗口大小(400x150)和位置(cx,cy),視窗會位於螢幕正中心
set cx [expr [lindex [get_screen_center] 0] - 200]
set cy [expr [lindex [get_screen_center] 1] -75]
wm geometry . 400x220+$cx+$cy; update
wm maxsize . 400 220
wm minsize . 400 220
#開一個frame
frame .frame1 -bd 2 -width 400 -height 220 -relief raised
place .frame1 -x 0 -y 0
#button
button .frame1.b1 -text "確定" -foreground #d97ed9 -font {bold 12} -command {
#cget取得widget當前給予option值
check_pass
}
place .frame1.b1 -x 50 -y 110
button .frame1.b2 -text "取消" -foreground #d97ed9 -font {bold 12} -command {
destroy .
#destroy .frame1
}
place .frame1.b2 -x 300 -y 110
button .frame1.b3 -text "重設" -foreground #d97ed9 -font {bold 12} -command {
set ::file_pass ""
}
place .frame1.b3 -x 175 -y 110
entry .frame1.t -textvariable ::file_pass -foreground #1413d9
place .frame1.t -x 100 -y 50
label .frame1.l1 -text "密碼:" -foreground #f90308
place .frame1.l1 -x 10 -y 50
label .frame1.l2 -text "請輸入root密碼" -foreground #368160
place .frame1.l2 -x 150 -y 10
###########################################check密碼是否ok#########################################################
##使用一點技巧,來判斷root密碼是否正確,把sudo ls結果放置/tmp/log_pass,若是空的代表密碼是錯誤的######################
###################################################################################################################
proc check_pass {} {
catch { exec echo $::file_pass | sudo -S ls > /tmp/log_pass }
set aa [exec cat /tmp/log_pass]
if { [string compare $aa ""] != 0 } then {
#密碼OK,執行./grub.t,並關閉視窗
#frame .frame2 -bd 2 -width 400 -height 220 -relief raised
place .frame2 -x 0 -y 0
#source ./grub.tk
#exec echo $::file_pass | sudo -S ./grub.tk &
destroy .frame1
} else {
set ::file_pass ""
#密碼是錯誤的重設lable的text
.frame1.l2 configure -foreground #f90308
.frame1.l2 configure -text "密碼錯誤,請重新輸入."
};#if
}
grub.tk
#!/usr/bin/wish
########################source 螢幕中心點程序############################
#source ./screen.tk
##############################取得變數color當前文字顏色名稱######################################################
proc get_color {color} {
set color_d [exec sed -n "s/$color=//gp" /usr/share/desktop-base/grub_background.sh]
#去掉/以後文字
regsub -all {/.*} $color_d "" color_1
return $color_1
}
##############################取得當前grub resolution###########################################################
proc get_grub_resolution {} {
set resolution [exec sed -n "s/^.*GRUB_GFXMODE=//gp" /etc/default/grub]
return $resolution
}
##############################取得grub是否隱藏##################################################################
proc get_grub_hidden_status { } {
set test [exec sed -n "s/^GRUB_HIDDEN_TIMEOUT=//gp" /etc/default/grub]
if { [string compare $test ""] != 0 } then {
return "YES" ;#true
} else {
#不隱藏grub,加入選擇秒數widget
#set test [exec sed -n "s/^#GRUB_HIDDEN_TIMEOUT=//gp" /etc/default/grub]
add_timout_widget
return "NO" ;#false
};#if
}
################################設定grub是否隱藏var=1 or 0##################################################################
proc set_grub_hidden { var } {
#GRUB_HIDDEN_TIMEOUT=0
#GRUB_TIMEOUT=10
if { $var } then {
exec sed "s/^.*GRUB_HIDDEN_TIMEOUT=/GRUB_HIDDEN_TIMEOUT=/g" /etc/default/grub > /tmp/grub_hident
exec sed "s/^.*GRUB_TIMEOUT=.*/GRUB_TIMEOUT=0/g" /tmp/grub_hident > /tmp/grub_hident1
puts YES
} else {
set timeout [.frame2.m4 cget -text]
#puts $timeout
exec sed "s/^.*GRUB_HIDDEN_TIMEOUT=/#GRUB_HIDDEN_TIMEOUT=/g" /etc/default/grub > /tmp/grub_hident
exec sed "s/^.*GRUB_TIMEOUT=.*/GRUB_TIMEOUT=$timeout/g" /tmp/grub_hident > /tmp/grub_hident1
puts NO
}
exec echo $::file_pass | sudo -S cp /tmp/grub_hident1 /etc/default/grub &
}
###########################設定grub_background.sh程序############################################################
proc set_grub_text_color_wallpaper {text stext } {
puts "$text $stext"
#WALLPAPER=/usr/share/images/desktop-base/desktop-grub.png
#COLOR_NORMAL=red/black
#COLOR_HIGHLIGHT=green/black
#GRUB_GFXMODE=640x480
set val1 [get_color "COLOR_NORMAL" ]
set val2 [get_color "COLOR_HIGHLIGHT"]
exec sed "s/COLOR_NORMAL=$val1/COLOR_NORMAL=$text/g" /usr/share/desktop-base/grub_background.sh > /tmp/grub_.cfg
exec sed "s/COLOR_HIGHLIGHT=$val2/COLOR_HIGHLIGHT=$stext/g" /tmp/grub_.cfg > /tmp/grub_1.cfg
exec echo $::file > /tmp/ttt
#change / -> \/
set file_c [eval exec ./t.sh /tmp/ttt]
exec sed "s/WALLPAPER=.*/WALLPAPER=$file_c/g" /tmp/grub_1.cfg > /tmp/grub_background.sh
exec echo $::file_pass | sudo -S cp /tmp/grub_background.sh /usr/share/desktop-base/grub_background.sh &
}
################################設定screen resolution###########################################################
proc set_grub_screen_resolution { resolution} {
puts [exec sed "s/^.*GRUB_GFXMODE=\.*/GRUB_GFXMODE=$resolution/g" /etc/default/grub > /tmp/grub]
exec echo $::file_pass | sudo -S cp /tmp/grub /etc/default/grub &
}
###################open file程序################################################################################
proc file_open {} {
set types {
{"圖片檔" {.png} }
}
#全局變數
# set ::file [tk_getOpenFile -filetypes $types -parent "."]
set ::file [tk_getOpenFile -filetypes $types -initialdir "~" -initialfile $::file]
}
#####################add widget################################################################################
proc add_timout_widget {} {
#試著加入widget,有可能error,所以用catch
catch {
set timeout_value [exec sed -n "s/^GRUB_TIMEOUT=//gp" /etc/default/grub]
set timeout_list [list 5 10 15 20 25 30 ]
#假如timeout_value不在list內就加入list
if { [lsearch $timeout_list $timeout_value] < 0 } then {
lappend timeout_list $timeout_value
}
label .frame2.tl -text "選單停留秒數:"
place .frame2.tl -x 200 -y 100
#eval tk_optionMenu .frame2.m4 timeout_var $timeout_list
eval tk_optionMenu .frame2.m4 timeout_var $timeout_list
place .frame2.m4 -x 280 -y 100
};#catch
}
###########################form layout##########################################################################
#建立窗口
#wm .main
#wm title . "GRUB工具箱"
#指定窗口大小(400x150)和位置(cx,cy),視窗會位於螢幕正中心
#set cx [expr [lindex [get_screen_center] 0] - 200]
#set cy [expr [lindex [get_screen_center] 1] -90]
#wm geometry . 400x220+$cx+$cy; update
#wm maxsize . 1028 512
#wm minsize . 128 1
#wm title . "GRUB工具箱"
frame .frame2 -bd 2 -width 400 -height 220 -relief raised
#place .frame2 -x 0 -y 0
#button
button .frame2.b1 -text "確定" -command {
#判定圖片file是否輸入,避免空白
label .l6 -text "更新中,請稍待!!"
place .l6 -x 10 -y 100
if { [string compare $::file ""] != 0 } then {
#設定文字顏色和Picture,註:cget取得widget當前給予option值
set_grub_text_color_wallpaper [.frame2.m1 cget -text] [.frame2.m2 cget -text]
#設定grub的resolution
set_grub_screen_resolution [.frame2.m3 cget -text]
#設定grub是否hidden
set_grub_hidden $var1
#####
button .rb -text "離開" -command {
destroy .
}
place .rb -x 160 -y 180
#加入文字區,高10,寬80的.text frame
source ./add_run_frame.tk
add_run_frame ".text" 80 10
#呼叫Run程序執行Linux指令,結果會出現在frame .text的文字區
Run "echo $::file_pass | sudo -S update-grub"
#update grub,記得要加&,否則error,先砍掉/boot/grub/grub.cfg,再出現,就是完成
#exec echo $::file_pass | sudo -S update-grub &
} else {
puts "圖片檔案不存在"
};#if
destroy .frame2
};#確定command
place .frame2.b1 -x 20 -y 180
button .frame2.b2 -text "離開" -command {
destroy .
}
place .frame2.b2 -x 250 -y 180
label .frame2.l1 -text "grub圖片:"
place .frame2.l1 -x 10 -y 130
#取得目前圖片檔位置,並設為全域變數
set ::file [eval exec sed -n "s/WALLPAPER=//gp" /usr/share/desktop-base/grub_background.sh ]
#輸入框
entry .frame2.t -textvariable ::file
place .frame2.t -x 100 -y 130
button .frame2.b3 -text "設定" -command {
file_open
}
place .frame2.b3 -x 280 -y 130
#tk_optionMenu menu
set menu_list {green red blue white black brown cyan dark-gray light-cyan light-blue \
light-green light-gray light-magenta light-red magenta yellow
}
#tk_optionMenu當使用list變數,記得前面要加eval
eval tk_optionMenu .frame2.m1 val1 $menu_list
eval tk_optionMenu .frame2.m2 val2 $menu_list
#tk_optionMenu menu1
#把預設也加入 screen resolution list,避免找不到
set menu_list_screen [get_resolution_all [get_grub_resolution]]
eval tk_optionMenu .frame2.m3 val3 $menu_list_screen
place .frame2.m1 -x 120 -y 10
place .frame2.m2 -x 120 -y 40
place .frame2.m3 -x 120 -y 70
#初始化設定tk_optionMenu預設值,由COLOR_NORMAL和COLOR_HIGHLIGHT決定來回傳顏色,和resolution
set val1 [get_color "COLOR_NORMAL" ]
set val2 [get_color "COLOR_HIGHLIGHT"]
#set val3 [lindex $menu_list_screen 0]
set val3 [get_grub_resolution]
#label
label .frame2.l2 -text "設定文字顏色:"
label .frame2.l3 -text "設定選取顏色:"
label .frame2.l4 -text "設定grub解析度:"
place .frame2.l2 -x 10 -y 10
place .frame2.l3 -x 10 -y 40
place .frame2.l4 -x 10 -y 70
#radio button
label .frame2.l5 -text "隱藏GRUB選單"
place .frame2.l5 -x 10 -y 100
radiobutton .frame2.rd -text "YES" -variable var1 -value "YES" \
-command {
puts $var1
#試著移除.frame2.m4,有可能error,所以用catch
catch {destroy .frame2.m4 }
catch {destroy .frame2.tl }
}
radiobutton .frame2.re -text "NO" -variable var1 -value "NO" \
-command {
puts $var1
# 加入選項
#set timeout_var [exec sed -n "s/^GRUB_TIMEOUT=//gp" /etc/default/grub]
add_timout_widget
}
#初始化var1
set var1 [get_grub_hidden_status ]
place .frame2.rd -x 100 -y 100
place .frame2.re -x 150 -y 100
#初始化timeout list(timeout_var),必須在主程序,在副程序會無作用
set timeout_var [exec sed -n "s/^GRUB_TIMEOUT=//gp" /etc/default/grub]
screen.tk
#!/usr/bin/wish
catch { exec xrandr > /tmp/xrandr_log }
####################回傳螢幕正中心##################################################################
proc get_screen_center {} {
#有可能例外,catch出來
#catch { exec xrandr > /tmp/xrandr_log }
set sc [lindex [exec cat /tmp/xrandr_log | grep \*] 0]
regsub -all {x} $sc " " sxy
set x [lindex $sxy 0] ;#
set y [lindex $sxy 1] ;#
set cx [expr ($x)/2]
set cy [expr ($y)/2]
set sc_list [list $cx $cy] ;# screen center list
return $sc_list ;#回傳screen center list
}
###########################回傳螢幕所有resolution###################################################
proc get_resolution_all { init } {
#取得所有resolution設成sc變數,注意get_screen_center要掀被呼叫,才會有/tmp/xrandr_log
set sc [exec ./screen.sh /tmp/xrandr_log]
#初始化list
set sc_list [list $init]
#把所有的值放入list
foreach var $sc {
if { [string compare $var $init] != 0 } then {
lappend sc_list $var
}
#puts "$var"
}
#回傳list
return $sc_list
}
add_run_frame.tk
#!/usr/bin/wish
##########################新加一個frme,給一個Linux指令,會顯示在此frame,根據網路上資料修改##########################
proc add_run_frame { var x y } {
global log run_frame
set run_frame $var
frame $run_frame
#文字區
set log [text $run_frame.log -width $x -height $y \
-yscrollcommand {$run_frame.scroll set}]
#拉動滾軸加入文字區
scrollbar $run_frame.scroll -command {$run_frame.log yview}
#滾軸layout,右側充滿y
pack $run_frame.scroll -side right -fill y
#文字區,左側,填滿xy,並隨視窗擴充
pack $run_frame.log -side left -fill both -expand true
#frame填滿xy,並隨視窗擴充
#pack $run_frame -side top -fill both -expand true
pack $run_frame -side top
#place $run_frame -x 0 -y 0
}
#############################LOG RUN################################################################################
proc Run {command} {
global input log but
if [catch {open "|$command |& cat"} input] {
$log insert end $input\n
} else {
fileevent $input readable Log
$log insert end $command\n
#$but config -text Stop -command Stop
}
}
proc Log {} {
global input log
if [eof $input] {
Stop
} else {
gets $input line
$log insert end $line\n
$log see end
}
}
# Stop the program and fix up the button
proc Stop {} {
global input but
catch {close $input}
#$but config -text "Run it" -command Run
}
screen.sh
#!/bin/bash#找尋開頭是空字元並有x出現,譬如 800x640 ............
cat $1 | awk '/^\ .*x/{print $1 }'
t.sh
#!/bin/bash
#轉換/成\/
sed -n 's/\//\\\//gp' $1
沒有留言:
張貼留言