Ysgrifennu GUI ar gyfer 1C RAC, neu eto am Tcl/Tk

Wrth i ni ymchwilio i'r pwnc o sut mae cynhyrchion 1C yn gweithio yn amgylchedd Linux, darganfuwyd un anfantais - diffyg offeryn aml-lwyfan graffigol cyfleus ar gyfer rheoli clwstwr o weinyddion 1C. A phenderfynwyd cywiro'r anfantais hon trwy ysgrifennu GUI ar gyfer y cyfleustodau consol rac. Dewiswyd Tcl/tk fel yr iaith ddatblygu fel, yn fy marn i, yr un mwyaf addas ar gyfer y dasg hon. Ac felly, hoffwn gyflwyno rhai agweddau diddorol ar yr ateb yn y deunydd hwn.

I weithio bydd angen dosbarthiadau tcl/tk ac 1C arnoch. Ac ers i mi benderfynu gwneud y gorau o alluoedd cyflwyno tcl / tk sylfaenol heb ddefnyddio pecynnau trydydd parti, bydd angen fersiwn 8.6.7 arnaf, sy'n cynnwys ttk - pecyn gydag elfennau graffig ychwanegol, y mae angen ttk arno'n bennaf. ::TreeView, mae'n caniatáu data arddangos ar ffurf strwythur coeden ac ar ffurf tabl (rhestr). Hefyd, yn y fersiwn newydd, mae'r gwaith gydag eithriadau wedi'i ail-weithio (y gorchymyn ceisio, a ddefnyddir yn y prosiect wrth redeg gorchmynion allanol).

Mae'r prosiect yn cynnwys sawl ffeil (er nad oes dim yn eich atal rhag gwneud popeth mewn un):

rac_gui.cfg - config rhagosodedig
rac_gui.tcl - prif sgript lansio
Mae'r cyfeiriadur lib yn cynnwys ffeiliau sy'n cael eu llwytho'n awtomatig wrth gychwyn:
function.tcl - ffeil gyda gweithdrefnau
gui.tcl - prif ryngwyneb graffigol
images.tcl - llyfrgell ddelweddau base64

Mae'r ffeil rac_gui.tcl, mewn gwirionedd, yn cychwyn y cyfieithydd, yn cychwyn newidynnau, yn llwytho modiwlau, yn ffurfweddu, ac yn y blaen. Cynnwys y ffeil gyda sylwadau:

rac_gui.tcl

#!/bin/sh
exec wish "$0" -- "$@"

# Устанавливаем текущий каталог
set dir(root) [pwd]
# Устанавливаем рабочий каталог, если его нет то создаём
set dir(work) [file join $env(HOME) .rac_gui]
if {[file exists $dir(work)] == 0 } {
    file mkdir $dir(work)    
}
# каталог с модулями
set dir(lib) "[file join $dir(root) lib]"

# загружаем пользовательский конфиг, если он отсутствует, то копируем дефолтный
if {[file exists [file join $dir(work) rac_gui.cfg]] ==0} {
    file copy [file join [pwd] rac_gui.cfg] [file join $dir(work) rac_gui.cfg]
} 
source [file join $dir(work) rac_gui.cfg]
# Код проверки наличия rac и правильности указания пути в конфиге
# если программа не найдена то будет выведен диалог для указания корректного пути
# и этот путь будет записан в пользовательский конфиг
if {[file exists $rac_cmd] == 0} {
    set rac_cmd [tk_getOpenFile -initialdir $env(HOME) -parent . -title "Укажите путь до rac" -initialfile rac]
    file copy [file join $dir(work) rac_gui.cfg] [file join $dir(work) rac_gui.cfg.bak] 
    set orig_file [open [file join $dir(work) rac_gui.cfg.bak] "r"]
    set file [open [file join $dir(work) rac_gui.cfg] "w"]
    while {[gets $orig_file line] >=0 } {
        if {[string match "set rac_cmd*" $line]} {
            puts $file "set rac_cmd $rac_cmd"
        } else {
            puts $file $line
        }
    }
    close $file
    close $orig_file
    #return "$host:$port"
    file delete [file join $dir(work) 1c_srv.cfg.bak] 
} else {
    puts "Found $rac_cmd"
}

set cluster_user ""
set cluster_pwd ""
set agent_user ""
set agent_pwd ""
## LOAD FILE ##
# Загружаем модули кроме gui.tcl так как его надо загрузить последним
foreach modFile [lsort [glob -nocomplain [file join $dir(lib) *.tcl]]] {
    if {[file tail $modFile] ne "gui.tcl"} {
        source $modFile
        puts "Loaded module $modFile"
    }
}
source [file join $dir(lib) gui.tcl]
source [file join $dir(work) rac_gui.cfg]

# Читаем файл со списком серверов 1С
# и добавляем в дерево
if [file exists [file join $dir(work) 1c_srv.cfg]] {
    set f [open [file join $dir(work) 1c_srv.cfg] "RDONLY"]
    while {[gets $f line] >=0} {
        .frm_tree.tree insert {} end -id "server::$line" -text "$line" -values "$line"
    }    
}

Ar ôl lawrlwytho popeth sydd ei angen a gwirio am bresenoldeb y cyfleustodau rac, bydd ffenestr graffigol yn cael ei lansio. Mae rhyngwyneb y rhaglen yn cynnwys tair elfen:

Bar offer, coeden a rhestr

Fe wnes i gynnwys y “goeden” mor debyg â phosibl i offer safonol Windows o 1C.

Ysgrifennu GUI ar gyfer 1C RAC, neu eto am Tcl/Tk

Mae'r prif god sy'n ffurfio'r ffenestr hon wedi'i gynnwys yn y ffeil
lib/gui.tcl

# установка размера и положения основного окна
# можно установить в переменную topLevelGeometry в конфиг программы
if {[info exists topLevelGeometry]} {
    wm geometry . $topLevelGeometry
} else {
    wm geometry . 1024x768
}
# Заголовок окна
wm title . "1C Rac GUI"
wm iconname . "1C Rac Gui"
# иконка окна (берется из файла lib/imges.tcl)
wm iconphoto . tcl
wm protocol . WM_DELETE_WINDOW Quit
wm overrideredirect . 0
wm positionfrom . user

ttk::style theme use clam

# Панель инсрументов
set frm_tool [frame .frm_tool]
pack $frm_tool -side left -fill y 
ttk::panedwindow .panel -orient horizontal -style TPanedwindow
pack .panel -expand true -fill both
pack propagate .panel false

ttk::button $frm_tool.btn_add  -command Add  -image add_grey_32
ttk::button $frm_tool.btn_del  -command Del -image del_grey_32
ttk::button $frm_tool.btn_edit  -command Edit -image edit_grey_32
ttk::button $frm_tool.btn_quit -command Quit -image quit_grey_32

pack $frm_tool.btn_add $frm_tool.btn_del $frm_tool.btn_edit -side top -padx 5 -pady 5
pack $frm_tool.btn_quit  -side bottom -padx 5 -pady 5

# Дерево с полосами прокрутки
set frm_tree [frame .frm_tree]

ttk::scrollbar $frm_tree.hsb1 -orient horizontal -command [list $frm_tree.tree xview]
ttk::scrollbar $frm_tree.vsb1 -orient vertical -command [list $frm_tree.tree yview]
set tree [ttk::treeview $frm_tree.tree -show tree 
-xscrollcommand [list $frm_tree.hsb1 set] -yscrollcommand [list $frm_tree.vsb1 set]]

grid $tree -row 0 -column 0 -sticky nsew
grid $frm_tree.vsb1 -row 0 -column 1 -sticky nsew
grid $frm_tree.hsb1 -row 1 -column 0 -sticky nsew
grid columnconfigure $frm_tree 0 -weight 1
grid rowconfigure $frm_tree 0 -weight 1

# назначение обработчика нажатия кнопкой мыши
bind $frm_tree.tree <ButtonRelease> "TreePress $frm_tree.tree"

# Список для данных (таблица)
set frm_work [frame .frm_work]
ttk::scrollbar $frm_work.hsb -orient horizontal -command [list $frm_work.tree_work xview]
ttk::scrollbar $frm_work.vsb -orient vertical -command [list $frm_work.tree_work yview]
set tree_work [
    ttk::treeview $frm_work.tree_work 
    -show headings  -columns "par val" -displaycolumns "par val"
    -xscrollcommand [list $frm_work.hsb set] 
    -yscrollcommand [list $frm_work.vsb set]
]
# Установка цветов для чередования в таблице
$tree_work tag configure dark -background $color(dark_table_bg)
$tree_work tag configure light -background $color(light_table_bg)

# Размещение элементов на форме
grid $tree_work -row 0 -column 0 -sticky nsew
grid $frm_work.vsb -row 0 -column 1 -sticky nsew
grid $frm_work.hsb -row 1 -column 0 -sticky nsew
grid columnconfigure $frm_work 0 -weight 1
grid rowconfigure $frm_work 0 -weight 1
pack $frm_tree $frm_work -side left -expand true -fill both

#.panel add $frm_tool -weight 1
.panel add $frm_tree -weight 1 
.panel add $frm_work -weight 1

Mae'r algorithm ar gyfer gweithio gyda'r rhaglen fel a ganlyn:

1. Yn gyntaf, mae angen i chi ychwanegu'r prif weinydd clwstwr (h.y., y gweinydd rheoli clwstwr (yn Linux, mae rheolaeth yn cael ei lansio gyda'r gorchymyn "/opt/1C/v8.3/x86_64/ras clwstwr —daemon")).

I wneud hyn, cliciwch ar y botwm "+" ac yn y ffenestr sy'n agor, nodwch gyfeiriad y gweinydd a'r porth:

Ysgrifennu GUI ar gyfer 1C RAC, neu eto am Tcl/Tk

Wedi hynny, bydd ein gweinydd yn ymddangos yn y goeden trwy glicio arno, bydd rhestr o glystyrau yn agor neu bydd gwall cysylltiad yn cael ei arddangos.

2. Bydd clicio ar enw'r clwstwr yn agor rhestr o swyddogaethau sydd ar gael ar ei gyfer.

3. …

Ac yn y blaen, h.y. i ychwanegu clwstwr newydd, dewiswch unrhyw un sydd ar gael yn y rhestr a gwasgwch y botwm “+” yn y bar offer a bydd yr ymgom ychwanegu newydd yn cael ei arddangos:

Ysgrifennu GUI ar gyfer 1C RAC, neu eto am Tcl/Tk

Mae'r botymau yn y bar offer yn cyflawni swyddogaethau yn dibynnu ar y cyd-destun, h.y. Yn dibynnu ar ba elfen o'r goeden neu'r rhestr a ddewisir, bydd un weithdrefn neu'r llall yn cael ei berfformio.

Edrychwn ar enghraifft y botwm ychwanegu (“+”):

Cod cynhyrchu botwm:

ttk::button $frm_tool.btn_add  -command Add  -image add_grey_32

Yma gwelwn, pan fydd y botwm yn cael ei wasgu, y bydd y weithdrefn “Ychwanegu” yn cael ei gweithredu, ei god:

proc Add {} {
    global active_cluster host
    # Определяем идентификатор выделенного элемента
    set id  [.frm_tree.tree selection] 
    # Определяем значение этого элемента
    set values [.frm_tree.tree item [.frm_tree.tree selection] -values]
    set key [lindex [split $id "::"] 0]
    # в зависимости от того что выделили будет запущена нужная процедура
    if {$key eq "" || $key eq "server"} {
        set host [ Add::server ]
        return
    }
    Add::$key .frm_tree.tree $host $values
}

Dyma un o fanteision cosi: gallwch chi basio gwerth newidyn fel enw gweithdrefn:

Add::$key .frm_tree.tree $host $values

Hynny yw, er enghraifft, os ydym yn pwyntio at y prif weinydd ac yn pwyso “+”, yna bydd y weithdrefn Add::server yn cael ei lansio, os yn y clwstwr - Ychwanegu::clwstwr ac yn y blaen (byddaf yn ysgrifennu am ble mae'r Mae “allweddi” angenrheidiol yn dod o ychydig isod), mae'r gweithdrefnau a restrir yn tynnu elfennau graffig sy'n briodol i'r cyd-destun.

Fel y gallech fod wedi sylwi eisoes, mae'r ffurflenni yn debyg o ran arddull - nid yw hyn yn syndod, oherwydd cânt eu harddangos gan un weithdrefn, yn fwy manwl gywir prif ffrâm y ffurflen (ffenestr, botymau, delwedd, label), enw'r weithdrefn Ychwanegu Lefel Uchaf

proc AddToplevel {lbl img {win_name .add}} {
    set cmd "destroy $win_name"
    if [winfo exists $win_name] {destroy $win_name}
    toplevel $win_name
    wm title $win_name $lbl
    wm iconphoto $win_name tcl
    # метка с иконкой
    ttk::label $win_name.lbl -image $img
    # фрейм с полями ввода
    set frm [ttk::labelframe $win_name.frm -text $lbl -labelanchor nw]
    
    grid columnconfigure $frm 0 -weight 1
    grid rowconfigure $frm 0 -weight 1
    # фрейм и кнопки
    set frm_btn [frame $win_name.frm_btn -border 0]
    ttk::button $frm_btn.btn_ok -image ok_grey_24 -command { }
    ttk::button $frm_btn.btn_cancel -command $cmd -image quit_grey_24 
    grid $win_name.lbl -row 0 -column 0 -sticky nw -padx 5 -pady 10
    grid $frm -row 0 -column 1 -sticky nw -padx 5 -pady 5
    grid $frm_btn -row 1 -column 1 -sticky se -padx 5 -pady 5
    pack  $frm_btn.btn_cancel  -side right
    pack  $frm_btn.btn_ok  -side right -padx 10
    return $frm
}

Paramedrau galwadau: teitl, enw delwedd yr eicon o'r llyfrgell (lib/images.tcl) a pharamedr enw ffenestr dewisol (diofyn .add). Felly, os cymerwn yr enghreifftiau uchod ar gyfer ychwanegu'r prif weinydd a chlwstwr, bydd yr alwad yn unol â hynny:

AddToplevel "Добавление основного сервера" server_grey_64

neu

AddToplevel "Добавление кластера" cluster_grey_64

Wel, gan barhau â'r enghreifftiau hyn, byddaf yn dangos y gweithdrefnau sy'n dangos ychwanegu deialogau ar gyfer gweinydd neu glwstwr.

Ychwanegu:: gweinydd

proc Add::server {} {
    global default
    # выводим основную форму
    set frm [AddToplevel "Добавление основного сервера" server_grey_64]
    # добавляем етки и поля ввода на эту форму
    label $frm.lbl_host -text "Адрес сервера"
    entry  $frm.ent_host
    label $frm.lbl_port -text "Порт"
    entry $frm.ent_port 
    $frm.ent_port  insert end $default(port)
    grid $frm.lbl_host -row 0 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_host -row 0 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_port -row 1 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_port -row 1 -column 1 -sticky nsew -padx 5 -pady 5
    grid columnconfigure $frm 0 -weight 1
    grid rowconfigure $frm 0 -weight 1
    #set frm_btn [frame .add.frm_btn -border 0]
    # переопределяем обработчик нажатия кнопки
    .add.frm_btn.btn_ok configure -command {
        set host [SaveMainServer [.add.frm.ent_host get] [.add.frm.ent_port get]]
        .frm_tree.tree insert {} end -id "server::$host" -text "$host" -values "$host"
        destroy .add
        return $host
    }
    return $frm
}

Ychwanegu::clwstwr

proc Add::cluster {tree host values} {
    global default lifetime_limit expiration_timeout session_fault_tolerance_level
    global max_memory_size max_memory_time_limit errors_count_threshold security_level
    global load_balancing_mode kill_problem_processes 
    agent_user agent_pwd cluster_user cluster_pwd auth_agent
    if {$agent_user ne "" && $agent_pwd ne ""} {
        set auth_agent "--agent-user=$agent_user --agent-pwd=$agent_pwd"
    } else {
        set auth_agent ""
    }
    # устанавливаем глобальные переменные ()
    set lifetime_limit $default(lifetime_limit)
    set expiration_timeout $default(expiration_timeout)
    set session_fault_tolerance_level $default(session_fault_tolerance_level)
    set max_memory_size $default(max_memory_size)
    set max_memory_time_limit $default(max_memory_time_limit)
    set errors_count_threshold $default(errors_count_threshold)
    set security_level [lindex $default(security_level) 0]
    set load_balancing_mode [lindex $default(load_balancing_mode) 0]
    
    set frm [AddToplevel "Добавление кластера" cluster_grey_64]
    
    label $frm.lbl_host -text "Адрес основного сервера"
    entry  $frm.ent_host
    label $frm.lbl_port -text "Порт"
    entry $frm.ent_port 
    $frm.ent_port  insert end $default(port)
    label $frm.lbl_name -text "Название кластера"
    entry  $frm.ent_name
    label $frm.lbl_secure_connect -text "Защищённое соединение"
    ttk::combobox $frm.cb_security_level -textvariable security_level -values $default(security_level)
    label $frm.lbl_expiration_timeout -text "Останавливать выключенные процессы через:"
    entry  $frm.ent_expiration_timeout -textvariable expiration_timeout
    label $frm.lbl_session_fault_tolerance_level -text "Уровень отказоустойчивости"
    entry  $frm.ent_session_fault_tolerance_level -textvariable session_fault_tolerance_level
    label $frm.lbl_load_balancing_mode -text "Режим распределения нагрузки"
    ttk::combobox $frm.cb_load_balancing_mode -textvariable load_balancing_mode 
    -values $default(load_balancing_mode)
    label $frm.lbl_errors_count_threshold -text "Допустимое отклонение количества ошибок сервера, %"
    entry  $frm.ent_errors_count_threshold -textvariable errors_count_threshold
    label $frm.lbl_processes -text "Рабочие процессы:"
    label $frm.lbl_lifetime_limit -text "Период перезапуска, сек."
    entry  $frm.ent_lifetime_limit -textvariable lifetime_limit
    label $frm.lbl_max_memory_size -text "Допустимый объём памяти, КБ"
    entry  $frm.ent_max_memory_size -textvariable max_memory_size
    label $frm.lbl_max_memory_time_limit -text "Интервал превышения допустимого объёма памяти, сек."
    entry  $frm.ent_max_memory_time_limit -textvariable max_memory_time_limit
    label $frm.lbl_kill_problem_processes -justify left -anchor nw -text "Принудительно завершать проблемные процессы"
    checkbutton $frm.check_kill_problem_processes -variable kill_problem_processes -onvalue yes -offvalue no    
    
    grid $frm.lbl_host -row 0 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_host -row 0 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_port -row 1 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_port -row 1 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_name -row 2 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_name -row 2 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_secure_connect -row 3 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.cb_security_level -row 3 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_expiration_timeout -row 4 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_expiration_timeout -row 4 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_session_fault_tolerance_level -row 5 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_session_fault_tolerance_level -row 5 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_load_balancing_mode -row 6 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.cb_load_balancing_mode -row 6 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_errors_count_threshold -row 7 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_errors_count_threshold -row 7 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_processes -row 8 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.lbl_lifetime_limit -row 9 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_lifetime_limit -row 9 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_max_memory_size -row 10 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_max_memory_size -row 10 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_max_memory_time_limit -row 11 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.ent_max_memory_time_limit -row 11 -column 1 -sticky nsew -padx 5 -pady 5
    grid $frm.lbl_kill_problem_processes -row 12 -column 0 -sticky nw -padx 5 -pady 5
    grid $frm.check_kill_problem_processes -row 12 -column 1 -sticky nw -padx 5 -pady 5
    # переопределяем обработчик
    .add.frm_btn.btn_ok configure -command {
        RunCommand "" "cluster insert 
        --host=[.add.frm.ent_host get] 
        --port=[.add.frm.ent_port get] 
        --name=[.add.frm.ent_name get] 
        --expiration-timeout=$expiration_timeout 
        --lifetime-limit=$lifetime_limit 
        --max-memory-size=$max_memory_size 
        --max-memory-time-limit=$max_memory_time_limit 
        --security-level=$security_level 
        --session-fault-tolerance-level=$session_fault_tolerance_level 
        --load-balancing-mode=$load_balancing_mode 
        --errors-count-threshold=$errors_count_threshold 
        --kill-problem-processes=$kill_problem_processes 
        $auth_agent $host"
        Run::server $tree $host ""
        destroy .add
    }
    return $frm
}

Wrth gymharu cod y gweithdrefnau hyn, mae'r gwahaniaeth yn weladwy i'r llygad noeth; byddaf yn canolbwyntio ar y triniwr botwm "Iawn". Yn Tk, gellir diystyru priodweddau elfennau graffig wrth weithredu rhaglen gan ddefnyddio'r opsiwn ffurfweddu. Er enghraifft, y gorchymyn cychwynnol i arddangos y botwm:

ttk::button $frm_btn.btn_ok -image ok_grey_24 -command { }

Ond yn ein ffurflenni ni, mae'r gorchymyn yn dibynnu ar y swyddogaeth ofynnol:

  .add.frm_btn.btn_ok configure -command {
        RunCommand "" "cluster insert 
        --host=[.add.frm.ent_host get] 
        --port=[.add.frm.ent_port get] 
        --name=[.add.frm.ent_name get] 
        --expiration-timeout=$expiration_timeout 
        --lifetime-limit=$lifetime_limit 
        --max-memory-size=$max_memory_size 
        --max-memory-time-limit=$max_memory_time_limit 
        --security-level=$security_level 
        --session-fault-tolerance-level=$session_fault_tolerance_level 
        --load-balancing-mode=$load_balancing_mode 
        --errors-count-threshold=$errors_count_threshold 
        --kill-problem-processes=$kill_problem_processes 
        $auth_agent $host"
        Run::server $tree $host ""
        destroy .add
    }

Yn yr enghraifft uchod, mae'r botwm “clogiog” yn cychwyn y weithdrefn ar gyfer ychwanegu clwstwr.

Yma mae'n werth gwyro tuag at weithio gydag elfennau graffig yn Tk - ar gyfer elfennau mewnbwn data amrywiol (mynediad, blwch combo, botwm gwirio, ac ati) mae paramedr wedi'i gyflwyno fel newidyn testun:

entry  $frm.ent_lifetime_limit -textvariable lifetime_limit

Mae'r newidyn hwn wedi'i ddiffinio yn y gofod enw byd-eang ac mae'n cynnwys y gwerth a gofnodwyd ar hyn o bryd. Y rhai. er mwyn cael y testun a gofnodwyd o'r maes, does ond angen i chi ddarllen y gwerth sy'n cyfateb i'r newidyn (wrth gwrs, ar yr amod ei fod wedi'i ddiffinio wrth greu'r elfen).

Yr ail ddull ar gyfer adfer y testun a gofnodwyd (ar gyfer elfennau o'r math mynediad) yw defnyddio'r gorchymyn cael:

.add.frm.ent_name get

Gellir gweld y ddau ddull hyn yn y cod uchod.

Mae clicio ar y botwm hwn, yn yr achos hwn, yn lansio'r weithdrefn RunCommand gyda'r llinell orchymyn a gynhyrchir ar gyfer ychwanegu clwstwr o ran rac:

/opt/1C/v8.3/x86_64/rac cluster insert  --host=localhost  --port=1540  --name=dsdsds  --expiration-timeout=0  --lifetime-limit=0  --max-memory-size=0  --max-memory-time-limit=0  --security-level=0  --session-fault-tolerance-level=0  --load-balancing-mode=performance  --errors-count-threshold=0  --kill-problem-processes=no   localhost:1545

Nawr rydym yn dod at y prif orchymyn, sy'n rheoli lansiad rac gyda'r paramedrau sydd eu hangen arnom, hefyd yn dosrannu allbwn gorchmynion i restrau a dychweliadau, os oes angen:

RunCommand

proc RunCommand {root par} {
    global dir rac_cmd cluster work_list_row_count agent_user agent_pwd cluster_user cluster_pwd
    puts "$rac_cmd $par"
    set work_list_row_count 0
    # открываем канал в неблокирующем режиме
    # $rac - команда с полным путём
    # $par - сформированные ключи запуска и опции    
    set pipe [open "|$rac_cmd $par" "r"]
    try {
        set lst ""
        set l ""
        # вывод команды добавляем в список списков
        while {[gets $pipe line]>=0} {
            #puts $line
            if {$line eq ""} {
                lappend l $lst
                set lst ""
            } else {
                lappend lst [string trim $line]
            }
        }
        close $pipe
        return $l
    } on error {result options} {
        # Запуск обработчика ошибок
        ErrorParcing $result $options
        return ""
    }
}

Ar ôl mewnbynnu data'r prif weinydd, bydd yn cael ei ychwanegu at y goeden, ar gyfer hyn, yn y weithdrefn Ychwanegu: gweinydd uchod, y cod canlynol sy'n gyfrifol:

.frm_tree.tree insert {} end -id "server::$host" -text "$host" -values "$host"

Nawr, trwy glicio ar enw'r gweinydd yn y goeden, rydyn ni'n cael rhestr o glystyrau a reolir gan y gweinydd hwnnw, a thrwy glicio ar glwstwr, rydyn ni'n cael rhestr o elfennau clwstwr (gweinyddwyr, infobases, ac ati). Gweithredir hyn yn y weithdrefn TreePress (ffeil lib/function.tcl):

proc TreePress {tree} {
   global host server active_cluster infobase
   # определяем выделенный элемент
    set id  [$tree selection]
   # устанавливаем нужные глобальные переменные
    SetGlobalVarFromTreeItems $tree $id
   # Определяем ключ и значение, т.е. именно тип выбранного элемента
    set values [$tree item $id -values]
    set key [lindex [split $id "::"] 0]
   # и в зависимости от того что выбрали будет запущена соответствующая процедура 
   # в пространстве имён Run
    Run::$key $tree $host $values
}

Yn unol â hynny, bydd Run::server yn cael ei lansio ar gyfer y prif weinydd (ar gyfer clwstwr - Rhedeg:: clwstwr, ar gyfer gweinydd sy'n gweithio - Run::work_server, ac ati). Y rhai. mae gwerth y newidyn $key yn rhan o enw'r elfen goeden a nodir gan yr opsiwn -id.

Gadewch i ni dalu sylw i'r weithdrefn

Rhedeg::server

proc Run::server {tree host values} {
    # получаем список кластеров требуемого сервера
    set lst [RunCommand server::$host "cluster list $host"]
    if {$lst eq ""} {return}
    set l [lindex $lst 0]
    #puts $lst
    # удаляем лишнее из списка
    .frm_work.tree_work delete  [ .frm_work.tree_work children {}]
    # читаем список
    foreach cluster_list $lst {
        # Заполняем список полученными значениями
        InsertItemsWorkList $cluster_list
        # обрабатываем вывод (список) для добавления данных в дерево
        foreach i $cluster_list {
            #puts $i
            set cluster_list [split $i ":"]
            if  {[string trim [lindex $cluster_list 0]] eq "cluster"} {
                set cluster_id [string trim [lindex $cluster_list 1]]
                lappend cluster($cluster_id) $cluster_id
            }
            if  {[string trim [lindex $cluster_list 0]] eq "name"} {
                lappend  cluster($cluster_id) [string trim [lindex $cluster_list 1]]
            }
        }
    }
    # добавляем кластеры в дерево
    foreach x [array names cluster] {
        set id [lindex $cluster($x) 0]
        if { [$tree exists "cluster::$id"] == 0 } {
            $tree insert "server::$host" end -id "cluster::$id" -text "[lindex $cluster($x) 1]" -values "$id"
            # добавляем элементы в кластер
            InsertClusterItems $tree $id
        }
    }
    if { [$tree exists "agent_admins::$id"] == 0 } {
        $tree insert "server::$host" end -id "agent_admins::$id" -text "Администраторы" -values "$id"
        #InsertClusterItems $tree $id
    }
}

Mae'r weithdrefn hon yn prosesu'r hyn a dderbyniwyd gan y gweinydd trwy'r gorchymyn RunCommand ac yn ychwanegu pob math o bethau i'r goeden - clystyrau, gwahanol elfennau gwraidd (sylfeini, gweinyddwyr gweithio, sesiynau, ac ati). Os edrychwch yn ofalus, fe sylwch ar alwad i'r weithdrefn InsertItemsWorkList y tu mewn. Fe'i defnyddir i ychwanegu elfennau at restr graffigol trwy brosesu allbwn y cyfleustodau rac consol, a ddychwelwyd yn flaenorol fel rhestr i'r newidyn $lst. Dyma restr o restrau sy'n cynnwys parau o elfennau wedi'u gwahanu gan colon.

Er enghraifft, rhestr o gysylltiadau clwstwr:

svk@svk ~]$ /opt/1C/v8.3/x86_64/rac connection list --cluster=783d2170-56c3-11e8-c586-fc75165efbb2 localhost:1545
connection     : dcf5991c-7d24-11e8-1690-fc75165efbb2
conn-id        : 0
host           : svk.home
process        : 79de2e16-56c3-11e8-c586-fc75165efbb2
infobase       : 00000000-0000-0000-0000-000000000000
application    : "JobScheduler"
connected-at   : 2018-07-01T14:49:51
session-number : 0
blocked-by-ls  : 0

connection     : b993293a-7d24-11e8-1690-fc75165efbb2
conn-id        : 0
host           : svk.home
process        : 79de2e16-56c3-11e8-c586-fc75165efbb2
infobase       : 00000000-0000-0000-0000-000000000000
application    : "JobScheduler"
connected-at   : 2018-07-01T14:48:52
session-number : 0
blocked-by-ls  : 0

Ar ffurf graffigol bydd yn edrych rhywbeth fel hyn:

Ysgrifennu GUI ar gyfer 1C RAC, neu eto am Tcl/Tk

Mae'r weithdrefn uchod yn dewis enwau'r elfennau ar gyfer y pennawd a'r data i lenwi'r tabl:

InsertItemsWorkList

proc InsertItemsWorkList {lst} {
    global work_list_row_count
    # установка чередования цвета для строки
    if [expr $work_list_row_count % 2] {
        set tag dark
    } else {
        set tag light
    }
    # разбор строк на пары ключ - значение
    foreach i $lst {
        if [regexp -nocase -all -- {(D+)(s*?|)(:)(s*?|)(.*)} $i match param v2 v3 v4 value] {
            lappend column_list [string trim $param]
            lappend value_list [string trim $value]
        }
    }
     # заполнение таблицы
    .frm_work.tree_work configure -columns $column_list -displaycolumns $column_list
    .frm_work.tree_work insert {} end  -values $value_list -tags $tag
    .frm_work.tree_work column #0 -stretch
    # установка заголовков
    foreach j $column_list {
        .frm_work.tree_work heading $j -text $j
    }
    incr work_list_row_count
}

Yma, yn lle gorchymyn syml [split $str ":"], sy'n rhannu'r llinyn yn elfennau wedi'u gwahanu gan " : " ac yn dychwelyd rhestr, defnyddir mynegiad rheolaidd, gan fod rhai elfennau hefyd yn cynnwys colon.

Mae'r weithdrefn InsertClusterItems (un o nifer o rai tebyg) yn syml yn ychwanegu rhestr o elfennau plentyn gyda dynodwyr cyfatebol i goeden yr elfen clwstwr gofynnol
InsertClusterItems

proc InsertClusterItems {tree id} {
    set parent "cluster::$id"
    $tree insert $parent end -id "infobases::$id" -text "Информационные базы" -values "$id"
    $tree insert $parent end -id "servers::$id" -text "Рабочие серверы" -values "$id"
    $tree insert $parent end -id "admins::$id" -text "Администраторы" -values "$id"
    $tree insert $parent end -id "managers::$id" -text "Менеджеры кластера" -values $id
    $tree insert $parent end -id "processes::$id" -text "Рабочие процессы" -values "workprocess-all"
    $tree insert $parent end -id "sessions::$id" -text "Сеансы" -values "sessions-all"
    $tree insert $parent end -id "locks::$id" -text "Блокировки" -values "blocks-all"
    $tree insert $parent end -id "connections::$id" -text "Соединения" -values "connections-all"
    $tree insert $parent end -id "profiles::$id" -text "Профили безопасности" -values $id
}

Gallwch ystyried dau opsiwn arall ar gyfer gweithredu gweithdrefn debyg, lle bydd yn amlwg sut y gallwch chi optimeiddio a chael gwared ar orchmynion ailadroddus:

Yn y weithdrefn hon, mae ychwanegu a gwirio yn cael eu datrys yn uniongyrchol:

InsertBaseItems

proc InsertBaseItems {tree id} {
    set parent "infobase::$id"
    if { [$tree exists "sessions::$id"] == 0 } {
        $tree insert $parent end -id "sessions::$id" -text "Сеансы" -values "$id"
    }
    if { [$tree exists "locks::$id"] == 0 } {
        $tree insert $parent end -id "locks::$id" -text "Блокировки" -values "$id"
    }
    if { [$tree exists "connections::$id"] == 0 } {
        $tree insert $parent end -id "connections::$id" -text "Соединения" -values "$id"
    }
}

Dyma ddull mwy cywir:

InsertProfileItems

proc InsertProfileItems {tree id} {
    set parent "profile::$id"
    set lst {
        {dir "Виртуальные каталоги"}
        {com "Разрешённые COM-классы"}
        {addin "Внешние компоненты"}
        {module "Внешние отчёты и обработки"}
        {app "Разрешённые приложения"}
        {inet "Ресурсы интернет"}
    }
    foreach i $lst {
        append item [lindex $i 0] "::$id"
        if { [$tree exists $item] == 0 } {
            $tree insert $parent end -id $item -text [lindex $i 1] -values "$id"
        }
        unset item 
    }
}

Y gwahaniaeth rhyngddynt yw'r defnydd o ddolen, lle mae'r gorchymyn(au) ailadroddus yn cael eu gweithredu. Pa ddull i'w ddefnyddio sydd yn ôl disgresiwn y datblygwr.

Rydym wedi ymdrin ag ychwanegu elfennau ac adalw data, nawr mae'n bryd canolbwyntio ar olygu. Gan, yn y bôn, defnyddir yr un paramedrau ar gyfer golygu ac ychwanegu (ac eithrio'r sylfaen wybodaeth), defnyddir yr un ffurflenni deialog. Mae'r algorithm ar gyfer galw gweithdrefnau ar gyfer ychwanegu yn edrych fel hyn:

Ychwanegu::$key->AddToplevel

Ac ar gyfer golygu fel hyn:

Golygu::$key-> Ychwanegu::$key->AddTopLevel

Er enghraifft, gadewch i ni gymryd golygu clwstwr, h.y. Ar ôl clicio ar enw'r clwstwr yn y goeden, pwyswch y botwm golygu yn y bar offer (pensil) a bydd y ffurflen gyfatebol yn cael ei harddangos ar y sgrin:

Ysgrifennu GUI ar gyfer 1C RAC, neu eto am Tcl/Tk
Golygu::clwstwr

proc Edit::cluster {tree host values} {
    global default lifetime_limit expiration_timeout session_fault_tolerance_level
    global max_memory_size max_memory_time_limit errors_count_threshold security_level
    global load_balancing_mode kill_problem_processes active_cluster 
    agent_user agent_pwd cluster_user cluster_pwd auth
    if {$cluster_user ne "" && $cluster_pwd ne ""} {
        set auth "--cluster-user=$cluster_user --cluster-pwd=$cluster_pwd"
    } else {
        set auth ""
    }
    # рисуем форму для кластера
    set frm [Add::cluster $tree $host $values]
    # меняем текст на метке
    $frm configure -text "Редактирование кластера"
    
    set active_cluster $values
    # получаем данные по выделенному кластеру
    set lst [RunCommand cluster::$values "cluster info --cluster=$active_cluster $host"]
    # заполняем поля
    FormFieldsDataInsert $frm $lst
    # выключаем поля, редактирование которых запрещено
    $frm.ent_host configure -state disable
    $frm.ent_port configure -state disable
    # переназначаем обработчик
    .add.frm_btn.btn_ok configure -command {
        RunCommand "" "cluster update 
        --cluster=$active_cluster $auth 
        --name=[.add.frm.ent_name get] 
        --expiration-timeout=$expiration_timeout 
        --lifetime-limit=$lifetime_limit 
        --max-memory-size=$max_memory_size 
        --max-memory-time-limit=$max_memory_time_limit 
        --security-level=$security_level 
        --session-fault-tolerance-level=$session_fault_tolerance_level 
        --load-balancing-mode=$load_balancing_mode 
        --errors-count-threshold=$errors_count_threshold 
        --kill-problem-processes=$kill_problem_processes 
        $auth $host"
        $tree delete "cluster::$active_cluster"
        Run::server $tree $host ""
        destroy .add
    }
}

Yn seiliedig ar y sylwadau yn y cod, mewn egwyddor, mae popeth yn glir, ac eithrio bod y cod triniwr botwm wedi'i ddiystyru a bod gweithdrefn FormFieldsDataInsert sy'n llenwi'r meysydd â data ac yn cychwyn y newidynnau:

Mewnosod FfurflenFieldsData

proc FormFieldsDataInsert {frm lst} {
    foreach i [lindex $lst 0] {
        # получаем список параметров и значений
        if [regexp -nocase -all -- {(D+)(s*?|)(:)(s*?|)(.*)} $i match param v2 v3 v4 value] {
            # меняем символы
            regsub -all -- "-" [string trim $param] "_" entry_name
            # заполняем данными
            if [winfo exists $frm.ent_$entry_name] {
                $frm.ent_$entry_name delete 0 end
                $frm.ent_$entry_name insert end [string trim $value """]
            }
            if [winfo exists $frm.cb_$entry_name] {
                global $entry_name
                set $entry_name [string trim $value """]
            }
            # для чекбоксов меняем значения
            if [winfo exists $frm.check_$entry_name] {
                global $entry_name
                if {$value eq "0"} {
                    set $entry_name no
                } elseif {$value eq "1"} {
                    set $entry_name yes
                } else {
                    set $entry_name $value
                }
            }
        }
    }
}

Yn y weithdrefn hon, daeth mantais arall o tcl i'r amlwg - mae gwerthoedd newidynnau eraill yn cael eu disodli fel enwau newidyn. Y rhai. i awtomeiddio llenwi ffurflenni a chychwyn newidynnau, mae enwau meysydd a newidynnau yn cyfateb i switshis llinell orchymyn y cyfleustodau rac ac enwau paramedrau allbwn gorchymyn gyda rhywfaint o eithriad - mae tanlinell yn disodli'r dash. ae swyddi wedi'u hamserlennu - gwadu yn cyfateb i'r cae ent_scheduled_jobs_gwadu ac amrywiol trefnu_swyddi_gwadu.

Gall ffurfiau ar gyfer adio a golygu fod yn wahanol yng nghyfansoddiad y meysydd, er enghraifft, gweithio gyda sylfaen wybodaeth:

Ychwanegu diogelwch gwybodaeth

Ysgrifennu GUI ar gyfer 1C RAC, neu eto am Tcl/Tk

Golygu diogelwch gwybodaeth

Ysgrifennu GUI ar gyfer 1C RAC, neu eto am Tcl/Tk

Yn y drefn olygu Golygu::infobase, mae'r meysydd gofynnol yn cael eu hychwanegu at y ffurflen; mae'r cod yn swmpus, felly nid wyf yn ei gyflwyno yma.

Trwy gyfatebiaeth, gweithredir gweithdrefnau ar gyfer ychwanegu, golygu, dileu ar gyfer elfennau eraill.

Gan fod gweithrediad y cyfleustodau yn awgrymu nifer anghyfyngedig o weinyddion, clystyrau, seiliau gwybodaeth, ac ati, i benderfynu pa glwstwr sy'n perthyn i ba weinyddwr neu system diogelwch gwybodaeth, mae nifer o newidynnau byd-eang wedi'u cyflwyno, y mae eu gwerthoedd wedi'u gosod bob un. amser i chi glicio ar yr elfennau o'r goeden. Y rhai. mae'r weithdrefn yn rhedeg yn gyson trwy'r holl elfennau rhiant ac yn gosod y newidynnau:

SetGlobalVarFromTreeItems

proc SetGlobalVarFromTreeItems {tree id} {
    global host server active_cluster infobase
    set parent [$tree parent $id]
    set values [$tree item $id -values]
    set key [lindex [split $id "::"] 0]
    switch -- $key {
        server {set host $values}
        work_server {set server $values}
        cluster {set active_cluster $values}
        infobase {set infobase $values}
    }
    if {$parent eq ""} {
        return
    } else {
        SetGlobalVarFromTreeItems $tree $parent
    }
}

Mae'r clwstwr 1C yn caniatáu ichi weithio gydag awdurdodiad neu hebddo. Mae dau fath o weinyddwr - gweinyddwr asiant clwstwr a gweinyddwr clwstwr. Yn unol â hynny, er mwyn gweithredu'n gywir, cyflwynwyd 4 newidyn byd-eang arall yn cynnwys mewngofnodi gweinyddwr a chyfrinair. Y rhai. os oes cyfrif gweinyddwr yn y clwstwr, bydd deialog yn cael ei arddangos i nodi'ch mewngofnodi a'ch cyfrinair, bydd y data'n cael ei gadw yn y cof a'i fewnosod ym mhob gorchymyn ar gyfer y clwstwr cyfatebol.

Cyfrifoldeb y weithdrefn ymdrin â gwallau yw hyn.

GwallParcio

proc ErrorParcing {err opt} {
    global cluster_user cluster_pwd agent_user agent_pwd
        switch -regexp -- $err {
        "Cluster administrator is not authenticated" {
            AuthorisationDialog "Администратор кластера"
            .auth_win.frm_btn.btn_ok configure -command {
                set cluster_user [.auth_win.frm.ent_name get]
                set cluster_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
            #RunCommand $root $par
        }
        "Central server administrator is not authenticated" {
            AuthorisationDialog "Администратор агента кластера"
            .auth_win.frm_btn.btn_ok configure -command {
                set agent_user [.auth_win.frm.ent_name get]
                set agent_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
        }
        "Администратор кластера не аутентифицирован" {
            AuthorisationDialog "Администратор кластера"
            .auth_win.frm_btn.btn_ok configure -command {
                set cluster_user [.auth_win.frm.ent_name get]
                set cluster_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
            #RunCommand $root $par
        }
        "Администратор центрального сервера не аутентифицирован" {
            AuthorisationDialog "Администратор агента кластера"
            .auth_win.frm_btn.btn_ok configure -command {
                set agent_user [.auth_win.frm.ent_name get]
                set agent_pwd [.auth_win.frm.ent_pwd get]
                destroy .auth_win
            }
        }
        (.+) {
            tk_messageBox -type ok -icon error -message "$err"
        }
    }
}

Y rhai. yn dibynnu ar yr hyn y mae'r gorchymyn yn ei ddychwelyd, bydd yr adwaith yn unol â hynny.

Ar hyn o bryd, mae tua 95 y cant o'r swyddogaeth wedi'i weithredu, y cyfan sydd ar ôl yw gweithredu gwaith gyda phroffiliau diogelwch a'i brofi =). Dyna i gyd. Ymddiheuraf am y stori crychlyd.

Mae'r cod ar gael yn draddodiadol yma.

Diweddariad: Gorffennais weithio gyda phroffiliau diogelwch. Nawr mae'r swyddogaeth wedi'i gweithredu 100%.

Diweddariad 2: lleoleiddio i Saesneg a Rwsieg wedi'i ychwanegu, mae gwaith yn win7 wedi'i brofi
Ysgrifennu GUI ar gyfer 1C RAC, neu eto am Tcl/Tk

Ffynhonnell: hab.com

Ychwanegu sylw