2024-09-27

Tcl/Tk 9.0.0

 Tcl/Tk 釋出了一個新的主要版本,9.0.0。

Tcl/Tk 9.0 的主要改變可以參考官網的網頁,以及 tcl-release-notes-9.0.0.md, tk-release-notes-9.0.0.md

2024-09-20

Tcl/Tk 8.6.15

Tcl/Tk 釋出了 8.6 系列的新版本,8.6.15

這個版本的主要更新內容可以參考 tcltk-release-notes-8.6.15.txt


2024-07-19

tcl-stbimage v1.1

tcl-stbimage


主要是整合來自 AndroWish project 的 source code,以及更新了 stb_image_resize2.h。

有點麻煩的地方是,AndroWish 有加入了 TkPhoto 相關的程式,並且使用動態載入的方式載入 Tk。但是這個套件一開始的目的就是希望能在沒有 Tk 的情況下使用 stb image 方面的功能;所以我目前並沒有整合 TkPhoto 這部份的程式。

2024-07-09

Tklib 0.8

Tklib is like Tcllib, a collection of many small packages providing utilities, except that packages here are expected to depend on Tk. Tklib specializes in utilities for GUI programming.

Standard Tk Library (tklib) 釋出了 v0.8 版。有興趣的可以參考相關的網頁

2024-05-17

The race to replace Redis

The race to replace Redis
redis (Tcler's Wiki)


雖然有點晚了(在三月發生的事情),不過事件持續中。Redis 資料庫更改授權,從 7.4 開始就不是 Open Source 軟體。Redeis 目前使用雙授權,其中 Server Side Public License (SSPL) 與 MongoDB 所使用的相同,不是 OSI 所認證的自由軟體授權(Redis 另外一個授權也不是!)。也因此有好幾個  Forks 出現,而各個 Linux distribution 需要找出可用的選項。

所以如果有人寫文章列出 Open Source Database,結果有 MongoDB(接下來 Redis 也是如此),你就知道這個文章的作者真的只是搜尋網路然後列出個名單,而他並不用心。

2024-05-16

tablelist v7.2 and Scrollutil v2.2

tablelist, Scrollutil 與 Mentry 都釋出了新版,可以參考作者的網頁

因為三個套件都是 Tklib 的套件,也可以下載 Tklib 最新的原始碼取得。

2024-05-09

ATOM to HTML

下面的程式使用 TclCurl 自網站下載 ATOM XML 的資料, 下載以後使用 tDom 分析並且將 title 與 link 的資料儲存為 html 格式。 只有使用自己的部落格資料測試過。

#!/usr/bin/env tclsh

package require TclCurl
package require tdom

proc get_atom {url} {
    try {
        set curlHandle [curl::init]
        $curlHandle configure -url $url -bodyvar result
        $curlHandle setopt CURLOPT_HTTP_VERSION 2TLS

        catch { $curlHandle perform } curlErrorNumber
        if { $curlErrorNumber != 0 } {
            throw error [curl::easystrerror $curlErrorNumber]
        }
    } on error {em} {
        error "Error: $em"
    } finally {
       $curlHandle cleanup
    }

    return $result
}

proc parse {XML ofname} {
    set doc [dom parse $XML]
    set root [$doc documentElement]
    set ns {xmlns http://www.w3.org/2005/Atom}
    $doc selectNodesNamespaces $ns
    set titleList [$root selectNodes //xmlns:entry/xmlns:title]
    set linkList [$root selectNodes {//xmlns:entry/xmlns:link[@rel='alternate']}]

    set out [open $ofname w 0666]
    foreach tnode $titleList lnode $linkList {
        set ntitle [$tnode text]
        set nlink [$lnode getAttribute href]

        puts $out "<a href=\"$nlink\">$ntitle</a><br>"
    }
    close $out
}

if {$argc == 2} {
    set url [lindex $argv 0]
    set ofile [lindex $argv 1]
} else {
    puts "Usage:"
    puts "\ttclsh atom2html.tcl url filename"
    exit
}

if {[catch {set data [get_atom $url]} err]} {
    puts $err
} else {
    parse $data $ofile
}

2024-04-17

Eclipse Mosquitto

Eclipse Mosquitto 是一套開放原始碼的 MQTT Broker。

在 openSUSE 安裝:

sudo zypper in mosquitto

如果要執行的話,使用 systemctl 啟動服務:

sudo systemctl start mosquitto

再來使用 tcl.mqttc 驗證是否可以正確連線。

Subscribe:
package require mqttc

mqttc client "tcp://localhost:1883" "USERSSub" 1 -cleansession 1
client subscribe  "MQTT Examples" 1
while 1 {
    if {[catch {set result [client  receive]}]} {
        puts "Receive error!!!"
        break
    }
    if {[llength $result] > 0} {
        puts "[lindex $result 0] - [lindex $result 1]"
        if {![string compare -nocase [lindex $result 1] "Exit"]} {
            break
        }
    }
}
client unsubscribe  "MQTT Examples"
client close
Publish:
package require mqttc

mqttc client "tcp://localhost:1883" "USERSPub" 1 -timeout 1000
client publishMessage "MQTT Examples" "Hello MQTT!" 1 0
client publishMessage "MQTT Examples" "Exit" 1 0
client close

先執行 Subscribe 的部份,再使用 Publish 發送訊息,確定可以正確執行。


下面是另外一個使用 tcl.mqttc 測試 Subscribe 與 Publish 功能的測試程式:

package require Thread
package require mqttc
catch {console show}

set ::gThread [thread::create {thread::wait} ]
set result 0

proc subscribe { } {
    thread::send -async $::gThread {
        package require mqttc

        mqttc client "tcp://localhost:1883" "USERTest1" 1 -cleansession 1
        client subscribe  "MQTT Examples" 1
        while 1 {
            if {[catch {set result [client  receive]}]} {
                puts "Receive error!!!"
                break
            }
            if {[llength $result] > 0} {
                puts "[lindex $result 0] - [lindex $result 1]"
                if {![string compare -nocase [lindex $result 1] "Exit"]} {
                    break
                }
            }
        }
        client unsubscribe  "MQTT Examples"
        client close
    } ::result
}

subscribe
puts "started test..."

after 250

mqttc client "tcp://localhost:1883" "USERTest2" 1 -timeout 1000
client publishMessage "MQTT Examples" "Hello MQTT!" 1 0
client publishMessage "MQTT Examples" "Exit" 1 0
client close

vwait ::result

2024-04-10

Apache HTTP Server and rivet-fcgi

這是之前在寫 rivet-fcgi 這個幫助我學習 FastCGI 的 prototype 時的筆記,關於 Apache HTTP Server 的,目前我沒有再重新測一次確定完全沒有問題,只是放在這裡先做個記錄。


簡介

Apache HTTP Server 是 Apache 軟體基金會的一個開放原始碼的網頁伺服器軟體,可以在大多數電腦作業系統中運行, 以其高擴充的能力以及眾多的 module 著稱。雖然現在效能被其它的網頁伺服器超過,但是也仍然是一個高效能的伺服器。

在 openSUSE 安裝 Apache2:

sudo zypper install apache2

檢查 Apache 版本:

sudo httpd -v

建立 ssl.conf 設定檔

[req]
prompt = no
default_md = sha256
default_bits = 2048
distinguished_name = dn
x509_extensions = v3_req

[dn]
C = TW
ST = Taiwan
L = Taipei
O = Orange Inc.
OU = IT Department
emailAddress = admin@example.com
CN = localhost

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.localhost
DNS.2 = localhost
IP.1 = 127.0.0.1

透過指令建立開發測試用途的自簽憑證

openssl req -x509 -new -nodes -sha256 -utf8 -days 3650 -newkey rsa:2048 \
-keyout apache.key -out apache.crt -config ssl.conf

將 apache.key 複製到 ssl.key 目錄,apache.crt 複製到 ssl.crt 目錄(需要使用 su 切換到 root 身份或者使用 sudo)。

將 /etc/apache2/vhosts.d/vhost-ssl.template 複製為 vhost-ssl.conf,並修改內容如下:

# Template for a VirtualHost with SSL
# Note: to use the template, rename it to /etc/apache2/vhost.d/yourvhost.conf.
# Files must have the .conf suffix to be loaded.
#
# See /usr/share/doc/packages/apache2/README.QUICKSTART for further hints
# about virtual hosts.
#
# This is the Apache server configuration file providing SSL support.
# It contains the configuration directives to instruct the server how to
# serve pages over an https connection. For detailing information about these
# directives see http://httpd.apache.org/docs/2.4/mod/mod_ssl.html
#
# Do NOT simply read the instructions in here without understanding
# what they do.  They're here only as hints or reminders.  If you are unsure
# consult the online docs. You have been warned.
#

<IfDefine SSL>
<IfDefine !NOSSL>

##
## SSL Virtual Host Context
##

<VirtualHost _default_:443>

    #  General setup for the virtual host
    DocumentRoot "/srv/www/htdocs"
    #ServerName www.example.com:443
    #ServerAdmin webmaster@example.com
    ErrorLog /var/log/apache2/error_log
    TransferLog /var/log/apache2/access_log

    #   SSL Engine Switch:
    #   Enable/Disable SSL for this virtual host.
    SSLEngine on

    #   OCSP Stapling:
    #   Enable/Disable OCSP for this virtual host.
    SSLUseStapling  on

    #   You can use per vhost certificates if SNI is supported.
    SSLCertificateFile /etc/apache2/ssl.crt/apache.crt
    SSLCertificateKeyFile /etc/apache2/ssl.key/apache.key
    #SSLCertificateChainFile /etc/apache2/ssl.crt/vhost-example-chain.crt

    #   Per-Server Logging:
    #   The home of a custom SSL log file. Use this when you want a
    #   compact non-error SSL logfile on a virtual host basis.
    CustomLog /var/log/apache2/ssl_request_log   ssl_combined

    <Directory />
        Options FollowSymLinks
        AllowOverride All
        #    Order deny,allow
        #    Deny from all
    </Directory>

    <Directory /srv/www/htdocs>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
    </Directory>

</VirtualHost>

</IfDefine>
</IfDefine>

主要就是 SSLCertificateFile 與 SSLCertificateKeyFile 這二個項目的設定,端視所放置的位置。


Apache 提供不同的 multiprocessing modules (MPMs) 可以使用,主要有下列的分別:

  • Prefork MPM
  • Worker MPM
  • Event MPM

HTTP/2 支援無法在 Prefork MPM 下執行,所以需要設定使用其它的 MPM,目前建議使用 Event MPM。

Enable http2 mod:

sudo a2enmod http2

Enable HTTP2 flag:

sudo a2enflag HTTP2

Switch from prefork to event:

sudo zypper remove apache2-prefork
sudo zypper install apache2-event

In /etc/sysconfig/apache2 make sure to set

APACHE_MPM="event"

APACHE_START_TIMEOUT="10"

重啟 Apache 2:

sudo systemctl restart apache2

To automatically start the apache server after a reboot:

sudo systemctl enable apache2

Apache 內建支援 CGI,default-server.conf 在目錄內啟用 CGI 與設定 handler 的設定如下:

ScriptAlias /cgi-bin/ "/srv/www/cgi-bin/"

# "/srv/www/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "/srv/www/cgi-bin">
    AllowOverride None
    Options +ExecCGI -Includes
    <IfModule !mod_access_compat.c>
        Require all granted
    </IfModule>
    <IfModule mod_access_compat.c>
        Order allow,deny
        Allow from all
    </IfModule>
</Directory>

Options +ExecCGI 就是允許執行 CGI 的設定。


檢查目前載入的模組:

sudo apache2ctl -M

FastCGI

Apache mod_fcgid 是 Apache Http Server 用來支援 FastCGI 協定的模組。 FastCGI 是另外一種克服 CGI 缺點的發展路線,也就是將網頁伺服器與應用程式伺服器分開的方式, 而程式會持續執行,這樣就不需要每一個請求都需要產生一個子行程來運行。

下面是在 openSUSE 安裝的方式:

sudo zypper install apache2-mod_fcgid

接下來設定 Apache Http Server 的部份。
首先允許必要的模式:

sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo a2enmod setenvif
sudo a2enmod fcgid

下面使用的方式配合 spawn-fcgi
我們需要撰寫 spawn-fcgi 的 systemd service,在 /usr/lib/systemd/system 目錄下建立 spawnfcgi.service,內容如下:

[Unit]
Description=Spawn FCGI service
After=nss-user-lookup.target

[Service]
Type=forking
Environment=WORKERS=1
ExecStart=/usr/bin/spawn-fcgi \
    -F ${WORKERS} \
    -u wwwrun \
    -g www \
    -s /var/run/%p.sock \
    -P /var/run/%p.pid \
    -- /usr/bin/rivet-fcgi
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

(其中 -u 指定 user,-g 指定 group,隨著平台的不同可能有不同的設定。
rivet-fcgi 是我自己撰寫的工具。)

下面是測試我自己寫的工具的設定。
修改 /etc/apache2/conf.d 目錄下的檔案 mod_fcgid.conf,內容如下:

##
#<FilesMatch "\.php$">
#    AddHandler fcgid-script .php
#    Options +ExecCGI
#    FcgidWrapper /srv/www/cgi-bin/php5 .php
#</FilesMatch>
##
DirectoryIndex index.rvt index.tcl
<FilesMatch "\.(rvt|tcl)$">
    SetHandler "proxy:unix:/var/run/spawnfcgi.sock|fcgi://localhost/"
    #CGIPassAuth on
</FilesMatch>

而後啟動(或重新啟動)spawn-fcgi 與 apache2 的服務,接著進行測試是否有正確設定。
(注意:PHP-FPM 也可以使用類似的設定手法,只是 spawn-fcgi 設定的部份變成為設定 php-fpm 的參數, 而 web server 這邊的副檔名參數與連線參數需要修改。)

參考資料

tcl-opencv v0.17

tcl-opencv

 

已經更新版本為 v0.17 一段時間,只是現在才發佈在這個部落格上。 主要是增加 BarcodeDetector 的支援,以及修正 test cases 的錯誤。

  • Implement command: BarcodeDetector
  • Implement command: stackBlur
  • Implement command: hasNonZero
  • Add ::cv::REDUCE_SUM2 option to ::cv::reduce