潮流特區

焦點文章

「心寒影滙2」大人細路齊齊玩盡Halloween!
創意生活
Cheers!・2025-10-08

2025嘅萬聖節,澳門新濠影滙為您準備好「驚嚇」同「歡樂」雙重體驗~膽大王必挑戰嘅「心寒片場」可以一站式體驗以七大電影為主題的解謎鬼屋,沉浸式感受被鬼嚇住動腦!一家大細都啱玩嘅「玩『懼』萬聖節」Toy Story 主題攤位遊戲、面部彩繪、免費爆谷同「Trick or Treat」等緊您! 9月19日至11月2日,無論您係膽大王定係家庭樂,總有一樣啱您玩! 門票現已發售,立即預訂:https://s.ctm.net/jpvOc 心寒片場 (Creepy Studio) |解謎鬼屋等您體驗 平時睇鬼片就多,親身被鬼追您又試過未?今個萬聖節,新濠影滙「心寒片場」解謎鬼屋強勢回歸!七大恐怖電影主題輪住嚇您 —《娃鬼回魂》、《鬼新娘迎親》、《邪靈娃娃》…… 一邊解謎一邊逃出,包您嚇到尖叫唔停口! 日期:2025年9月19日至11月2日(逢星期五至日)時段: 下午 15:00 - 19:00(最後入場 18:30) 晚上 19:00 - 23:00(最後入場 22:30) 地點:澳門新濠影滙一樓(巨星酒廊對面) 膽大王想獨闖「心寒片場」?標準門票MOP $144即刻出發,新濠會員更可享9折優惠!如果自問「膽細細又驚又要玩」,不如拉埋班FD一齊挑戰四人行套票,MOP 444(原價MOP $576)平均每人只需MOP $111,抵玩又刺激~ 專程從香港過來玩?咁就一定要訂「港澳船票套票」啦!MOP $404即包「心寒片場」門票1張同香港澳門來回船票1套(「香港-澳門」船票僅限於門票當天或提前一日使用;「澳門-香港」需於門票當日計算七日內來使用。),原價成MOP $584,而家慳咗成百幾蚊真係超值! 玩完驚到餓?我哋幫您諗埋~「心寒片場」星滙自助午餐套票 MOP $404(原價MOP $538),包「心寒片場」門票同自助午餐1位 (*僅限門票當日或翌日使用) ;或者選擇「嘉宴」餐飲禮券套票 MOP 404(原價MOP $544),包「心寒片場」門票同MOP $400餐飲禮券,等您可以盡情補充能量!(*僅限活動期間使用) 無論獨闖、組隊、定係遠道而來,總有一套啱您玩!立即預訂:https://s.ctm.net/jpvOc 玩「懼」萬聖節|一家大細放心玩~遊戲攤位+面部彩繪+免費爆谷! 萬聖節小朋友Cos得咁得意,點可以唔帶佢哋出嚟威?今個萬聖節就去「澳門新濠影滙一樓時代廣場」!場內設有多個《反斗奇兵》主題攤位遊戲,MOP$20換一個遊戲代幣,挑戰成功即有機會贏得Toy Story獨家禮品,大人細路都玩得開心! 新濠會員尊享優惠: MOP $200 換10個遊戲代幣,免費送「反斗奇兵三眼仔糖果桶」,小朋友可以拎住去Trick or Treat啦! 面部彩繪體驗:用2個遊戲代幣,即可為小朋友畫超應節嘅萬聖節彩繪,可愛定恐怖任您揀! 免費爆谷派發:喺時代廣場(DFS 附近)仲有免費派發爆谷,首200名客人更可獲《反斗奇兵》主題爆谷,送完即止! 遊戲攤位開放時間:2025年9月19日至11月2日(逢星期五至日) 時間:13:00 - 21:00 (面部彩繪體驗 & 爆谷派發時間:13:00 – 18:00 ) 地點:澳門新濠影滙1樓時代廣場 Trick or Treat?|糖果大放送! 小朋友最愛環節嚟啦!9月19日至11月2日期間(每日都有!),只要喺新濠影滙精選商戶門口大叫「Trick or Treat?」,即可免費拎糖!實現糖果大豐收~ 萬聖節點止有得玩?新濠影滙「搞怪美食」驚喜登場! 玩到肚餓?唔使驚!新濠影滙四間餐廳齊推萬聖節主題限定套餐,搞怪得黎又好味,絕對係視覺與味覺嘅雙重享受~ 載運美式餐室嘅木乃伊開心套餐 / 骷髏骨頭開心套餐 / 惡魔魅影開心套餐,隨餐仲送萬聖節公仔掛飾,即時補充您係鬼屋尖叫流失嘅能量! 甜品控必衝羅浮餅廊及輕食嘅造型蛋糕, 小編最期待嘅就係「骷髏朱古力紅桑子蛋糕」同「紅桑子十字架丹麥 」,造型驚悚但味道驚喜,保證您相機食先! 想同朋友Chill 住打卡? 巨星酒廊萬聖節Tea Set絕對唔輸蝕 — 「怪獸之眼」、「吸血南瓜」、「木乃伊手指」、「女巫紅寶石」… ……款款精緻得嚟帶點詭異,包您一邊驚一邊笑! 最後當然唔少得星滙餐廳自助餐,多款萬聖主題美食任您放題,仲有一系列可愛到「嚇死人」嘅甜品,等您視覺同味覺同時被攻擊! 驚聲睇好戲|萬聖節電影優惠 喺鬼屋尖叫完,點可以唔睇返場戲壓壓驚?活動期間憑當日「心寒片場」門票,或者著住萬聖節服飾,去「影滙戲院」買飛即享: 第二張戲飛只要 MOP 60元! (即場出示當日「心寒片場」門票或穿著萬聖節主題服飾即享優惠) 一邊食爆谷一邊睇戲,萬聖節之旅完美收官~ 活動日期:2025年9月19日至11月2日地點:澳門新濠影滙戲院票務處 今個萬聖節唔使諗去邊,新濠影滙包大人同細路盡興而歸!記得約實朋友、帶埋一家大細嚟玩啦!

最新文章

AI 寫Code,可以真的讓我們解放雙手嗎?
科技新知
MacauYeah・2026-02-27

用過AI查資料寫Code後,筆者的確覺得是比傳統自己Google更有生產力。但長期使用下去,我們又該如何看待AI的生成物?理想地,以Copilot的方式,靠著AI寫出人都能看得懂,當然很好。但如果AI 什麼都懂,就讓AI自己維護自己就好。 重點應該是實現持續發展 傳統上, 能動能讀,通常就代表可以持續發展。但如果只以AI來編寫,是不是可以AI自己維護自己的程式了? 現階段看來是不可能的,一來是因為現時AI的精準度未夠高,我們只少要介入讓AI知道正向或逆向反饋。只有我們才能了解自己的需求,我們才能好好地驗收。 二來,就是當一件事越來越複雜的時候,不可能三言兩語就可以精準地描述我們想要的功能。雖然可能大部份人會認為,我們可以很簡單地描述出需求,並讓AI通過自我修正,直到找到結果。但寫過需求管理的朋友都知道,好好表達需求並不容易,如果可以很詳盡地寫出規則,其實pseudo code都完成了。就像人類社會的管理層一樣,上司很簡單地提出一個概念,下屬去思考再執行。除非下屬就是上司本人,否則不可能對同一個概念有完全一樣的理解。用一個更極端的例子來講,我們不可能將資訊無限量壓縮,最後就只會得0和1這個二元分類,也就是一些概念不可能無限地精簡。 所以不論AI可以如何代工,都不會讓我們可以完全省力,特別是在寫程式這一塊。它是減少我們重新發明車輪的工具,讓我們可以更早地面對未解決的問題。 所以筆者認為,可以人腦好好地理解AI寫出來的程式,一定會比只讓AI自己閱讀自己寫出來的程式走得更遠。像以前查書一樣,千鿋年變成Google後,查找快了,資訊流動快了,但人始終要理解資訊。而現在經過AI後,一些重複的工作,可以變得更有效率了,可以迭代的速度,道理上可以更快了,但人始終要知道自己為了什麼目標而迭代。

架設 Squid proxy,作為國産 Linux RPM 安裝包更新的 RPM proxy
科技新知
MacauYeah・2026-02-26

前編我們介紹了 Qemu 運行國産OS做快速測試。應該基本使用大家都可以實驗到。 在投産環境上,我們通常還要控制它的kernel或lib版本更新,但這麼多的不同OS版本,想一次過做rpm mirror,並不太實際。 若以監管為目標,那些不同種類的OS,限制互聯網存取,統一經過某個http proxy的取得RPM更新,應該是一個最低成本的做法。 本文就來介紹一下,使用Ubuntu 24建設 Squid http proxy,達到rpm proxy的結果。 ubuntu 24.04 squid settings apt-get update && apt-get install squid vim /etc/squid/squid.conf 約在1404行,指定一個新的acl(access control list)名字,fixip, 它的允許來源IP是你的rpm base OS # around line 1404, add acl fixip src xxx.xxx.xxx.xxx 約在1627行, 放行新的acl # around line 1627, add http_access allow fixip rpm os settings 在rpm base的OS上,通常在 /etc/yum.repos.d/ 低下就找到它們的 rpm 包來源為置,在每個來源上加上 proxy 設定,就可以了。 Anolis OS 8 因為rpm來源眾多,我們只想讓其中兩個經proxy更新,例如 /etc/yum.repos.d/AnolisOS-AppStream.repo, /etc/yum.repos.d/AnolisOS-BaseOS.repo, 最在後加入 proxy=http://yyy.yyy.yyy.yyy:3128。 yyy.yyy.yyy.yyy 就是設了 Squid的機器 [AppStream] name=AnolisOS-$releasever - AppStream baseurl=http://mirrors.openanolis.cn/anolis/$releasever/AppStream/$basearch/os enabled=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ANOLIS gpgcheck=1 proxy=http://yyy.yyy.yyy.yyy:3128 [BaseOS] name=AnolisOS-$releasever - BaseOS baseurl=http://mirrors.openanolis.cn/anolis/$releasever/BaseOS/$basearch/os enabled=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ANOLIS gpgcheck=1 proxy=http://yyy.yyy.yyy.yyy:3128 OpenEuler 22 來源檔只有一個,/etc/yum.repos.d/openEuler.repo, 但內存多個section, 需要在每個section的尾段,加入 proxy=http://yyy.yyy.yyy.yyy:3128 [OS] name=OS baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/OS/$basearch/ metalink=https://mirrors.openeuler.org/metalink?repo=$releasever/OS&arch=$basearch metadata_expire=1h enabled=1 gpgcheck=1 gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/OS/$basearch/RPM-GPG-KEY-openEuler proxy=http://yyy.yyy.yyy.yyy:3128 [everything] name=everything baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/everything/$basearch/ metalink=https://mirrors.openeuler.org/metalink?repo=$releasever/everything&arch=$basearch metadata_expire=1h enabled=1 gpgcheck=1 gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/everything/$basearch/RPM-GPG-KEY-openEuler proxy=http://yyy.yyy.yyy.yyy:3128 ... ... [update] name=update baseurl=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/update/$basearch/ metalink=https://mirrors.openeuler.org/metalink?repo=$releasever/update&arch=$basearch metadata_expire=1h enabled=1 gpgcheck=1 gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS-SP4/OS/$basearch/RPM-GPG-KEY-openEuler proxy=http://yyy.yyy.yyy.yyy:3128 ... ... 指令 我們可以先用curl,來測試一下最基本的連線。請確保指令是在最初定義的xxx.xxx.xxx.xxx範圍內。 curl -v -x http://yyy.yyy.yyy.yyy:3128 http://mirrors.openanolis.cn/anolis/8.10/ 部份更新指令 由於我們前述 rpm 包並不是所有都加了proxy,我們只限定某些進行更新,所以我們使用--disablerepo --enablerepo來限制指定的更新來源。 # anolis dnf install --disablerepo='*' --enablerepo='BaseOS' 'tmux' dnf upgrade --disablerepo='*' --enablerepo='kernel-5.10' 'kernel*' # openeuler dnf install --disablerepo='*' --enablerepo='everything' tmux dnf upgrade --disablerepo='*' --enablerepo='update' 'kernel*' 參考連結 squid tutorial https://www.digitalocean.com/community/tutorials/how-to-set-up-squid-proxy-on-ubuntu-20-04 yum proxy tutorial https://www.baeldung.com/linux/yum-dnf-repositories-set-proxy

Steam OS 3.7 桌面模式下的中文輸入法 fcitx5+RIME
科技新知
MacauYeah・2026-02-21

上一篇我們提到,SteamOS的原生鍵盤不知為何失效,我們在桌面模式上的另一個選擇就是flatpak中的 Fcitx5。 因為Fcitx5是基於flapak安裝的,預設只在flapak下通用,後半部份,亦會介紹如何打破這個限制。 安裝Fcitx5 及倉頡五 我們可以在 Discovery App,輸入關鍵字 Fcitx5, 找到相關的套件。為更精準地安裝指定套件,可以直接在terminal 使用以下指令。 首次啟動時,需在start menu中,搜尋fcitx5,它就會長註在右下角的系統列中,選該icon→右鍵→input method settings,把「RIME」加入到fcitx5中,就可以使用了。 在此時,你可以打開Firefox,經control+space的方式轉換輸入法試試。但之後你會發現,原生的Kate文字軟件,都無辦法輸入中文。因為只有Dsicovery / flatpak 的 app 才能正常使用fcitx5。 大範圍套用Fcitx5 如果你找網上或AI的資訊,大部都會提示你修改系統設定檔,把fcitx5加到其中,但筆者就不成功。好在有[Bilibili強者的筆記](https://www.bilibili.com/opus/1139601518269300768](https://www.bilibili.com/opus/1139601518269300768)),原來SteamOS自帶的是ibus,但ibus又不讓設定(因為要換rootfs)。我們通過flatpak中安裝fcitx5,其實是可以通過ibus存到系統的。步驟如下: 如果你還未為當前的deck user配上密碼,你可以在terminal中使用 有密碼後,就可以使用 把所有module加為ibus 你沒有看錯,真的是那樣。基在上所有原生的桌面app及terminal,也可以切為到中文輸入法了。還有一個特例就是經 distrobox 生成的環境,依然無法存入ibus。 Reference https://www.bilibili.com/opus/1139601518269300768

2026看Steam Machine | Steam OS 是不是一個出路?
科技新知
MacauYeah・2026-02-20

在這幾年,筆者都一直分享一些coding anywhere的主題。原本的出發點,其實是因為雲資源及container的出現,是不是讓個人電腦的採購可以越來越不受限?是不是相對選擇會更多,亦應該可以更便宜的選擇? 適逢SteamDeck Linux興起,使用Steam OS道理上會比windows更適配雲資源的開發,而且SteamDeck 可以同步作為手提遊戲機,買台低配的SteamDeck回來,可謂一石多鳥。筆者用著用著,也來了兩年多。現在再來聊它,主要因為Valve未來又有新的硬件Steam Machine推出。這台新硬件,道理上也是跟Steam OS,官方亦宣傳它可以作為PC用。但就這一賣點,筆者很想分享一下它的Steam Deck的使用心得,供各位參考Steam Machine的軟功能是否適合。 https://store.steampowered.com/sale/steammachine 首先,作為遊戲方面,Steam Deck是手提遊戲,硬件比較弱,不能與同世代的PS5或Xbox Series X或PC去對比。我們不應該拿畫面和效能跟其他平台比。但它的OS 層功能,就很直接看得出它有沒有價值。 遊戲模式-Gaming mode 有即時待機功能,但不是所有遊戲都百分百適配。Steam OS的待機,來回玩,再待機,玩過兩三天,總會crash一次。相對之下,Switch就做得很好,就算玩一週也沒問題。Steam OS 也不能說很差,因為PS5等沒有真試過來回待機玩個一週。這裏要表達的,就是遊戲未必為Steam OS而做優化,開發商的目標還是傳統的PC遊戲模式,傳統PC Notebook也有待命,但又有多少遊戲會認真對待?所以Steam OS可以待個兩天,就已經很好 手柄連接算是順利,一般大版的手柄,都可以簡單連接。但它也有做得不好的地方。每次待機換地點,基本上都涉及切換手柄問題。即使內置就有只一個實體手柄,系統並不會自動為你更換第一順位。例如,我原本使用PS5 無線手柄,在家遊玩,這時PS5手柄是第一順位,實體手柄是第二順位。很多遊戲只認第一順位是很正常的。不過在我待機,切換環境,原本的PS5手柄已不存在,但SteamOS並不會把實體手柄順移到第一順位,必需要手動調節。好在,也不需要退遊戲就可以切換。這個對比PC來講,SteamOS已經是做出了改進,但對於Switch和PS4/5,這些根本就是待機一啟動時就要為用戶的問題。可能這是因為SteamOS要考慮Desktop Mode的原因吧,不過筆者就沒有試過在Desktop Mode開遊戲,因為突然要待機外出會更麻煩。 桌面模式-Desktop Mode 這個模式,筆者就專注在取待PC的日常操作上 中日韓輸入法問題,這是大大地阻礙大家入這坑的很重要原因。如果大家都是純英文人,就不需要顧慮這一塊。但筆者就不是一個英文很強的人,多多少少需要直接打中文去找問題。原本SteamOS在Gaming Mode下可以通過 Steam Key + X,叫出虛擬鍵盤,安裝中文倉頡是很易的事。原本這一功能,在Desktop Mode也是可以的。但在寫稿的今天,Gaming Mode / Desktop Mode的中文虛擬鍵盤都一起報廢了,原因未明。筆者只好走回最早期為大家介絡的 flatpak fcitx5+RIME大法。fcitx5可以用,但限制也多。之後筆者再寫一期教學,解決它的限制問題。 辦公室套件。最基本就LibreOffice, OnlyOffice,大家可以在Desktop Mode中的Discovery裏找到。大家想知自己常用的套件是否有對應的版本,可以在https://flathub.org/en 裏找找看。有的話基本可以放心一半,至少經Discovery下載的app,都可以經fcitx5+RIME輸入中文。但這並不代表你可以真的當自己在辦公室工作,那些printer / scanner ,筆者實在沒有太多想法。道理上今年今日普通列印功能,應該通過指定driver就可以做到,但無耐真的不太簡單。日後筆者了解好制式問題後,再來填這個坑。 瀏覽器-就用Firefox吧。 其他瀏覽器有是有的,但最好只用Firefox。Discovery是有筆者最常用的google chrome瀏覽器,但在網安原因下,筆者不敢推薦。Flathub上 Firefox是官方認證的程式,但Google Chrome和Chromium也是沒有認證。如果想使用管方認證的Google Chrome,頂多只能在Distrobox下自行安裝。同樣,如果你是IT人也是英文人,Distrobox再安裝chrome,應該很簡單。但如果你像筆者一樣,還是依賴中文輸入法,你就會很失望,Distrobox經X-server出來的程式,沒法使用前文所講的fcitx5。所以簡單一點的選擇,就是直接使用Firefox。 寫Code,那就得在Distrobox上弄了 Flathub上是有非管方的VSCode,但同樣問題,這個版本你敢用嗎?同樣地,在Distrobox 下安裝 VSCode,是取得官方版本的好方式。只要大家不強求在vscode中輸入中文就可以了(貼上中文是可以的)。使用Dsitrobox做開發類的IT工作,在Contianer範圍內,都算可行的,在Container內安裝java,總比在SteamOS上簡易。但如果你需做一些低層的開發,還是在VM下操作吧。 總結: 如果你很想一石多鳥,你能接受新事物,Steam OS可以一試。 如果你有一些深度的操作或要求,即是是遊戲層面還是工作層面,現時Steam OS都不是一個很好的選擇,除非你的Steam OS不更新,把它硬改回ArchLinux,但這就失去了Gaming Mode的意義。

雲系統的持續更新,大家的選擇是什麼?
科技新知
MacauYeah・2026-01-30

在開始之前,筆者先解釋一下自己對Linux發佈策略的理解。筆者之前以為自己都尚算了解,但到了兩難問題時,才開始反思。所以都不禁懷疑自己的基本觀念有沒有問題,如果大家覺得筆者多少有些理解上的錯誤,請留言糾正。 普通軟件的發佈 主要分為穩定(Stable / GA), 測試(Edge / Alpha / Beta),特定版本。穩定、測試版本也可能有多個不同的分支,但它們主要是指不同環境下的選擇。通常安裝時,都會安裝最後的穩定、測試,除非最後版本有明顯Bug,我們需要回覆到再去的一個穩定版本。 當我們每次都更新到最後的穩定版本,我們稱之為rolling release. 以docker 官方建議的方式,我們在ubuntu底下,可以看到它的有很多結果回傳。 apt list --all-versions docker-ce Listing... Done docker-ce/noble,now 5:29.1.4-1~ubuntu.24.04~noble amd64 [installed] docker-ce/noble 5:29.1.3-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:29.1.2-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:29.1.1-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:29.1.0-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:29.0.4-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:29.0.3-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:29.0.2-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:29.0.1-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:29.0.0-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:28.5.2-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:28.5.1-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:28.5.0-1~ubuntu.24.04~noble amd64 docker-ce/noble 5:28.4.0-1~ubuntu.24.04~noble amd64 ... 我們可以選擇過去某個版本,但通常無腦update,就會去到最後一個版本。 Ubuntu的發佈策略 我們換個package看看,如果只看重要軟件的話,例如kernel,我們沒有什麼可以選擇 apt list --all-versions linux-image-generic Listing... Done linux-image-generic/noble-updates,noble-security,now 6.8.0-90.91 amd64 [installed] linux-image-generic/noble 6.8.0-31.31 amd64 apt list --all-versions linux-image-virtual Listing... Done linux-image-virtual/noble-updates,noble-security,now 6.8.0-90.91 amd64 [installed,automatic] linux-image-virtual/noble 6.8.0-31.31 amd64 除了可選擇數量外,另一個最大的不同是,kernel的自身版本其實固定在 6.8.0,就算更新,都是同一個版本的ubuntu補丁版,並不是官方kernel的bug fix版。筆者認為,這應該就是所謂的point release的策略。 (如果大家安裝物理機的話,kernel可能會是6.14,筆者大部份都是VM,還是比較舊的版本。筆者保證,6.8.0-90.91與 6.8.0-31.31之間,曾經是有多個不同版本的。但現在沒法下載回來,除非之前大家有安裝過。) 但相同情況,我們找另一個package看看,由 ubuntu 自己打包的docker 版本,雖然可以選擇的數量是有限的,但它們的版本是不斷更新的,而且不是hotfix版,還有大版本更新。 apt list --all-versions docker.io Listing... Done docker.io/noble-updates,now 28.2.2-0ubuntu1~24.04.1 amd64 [installed] docker.io/noble-security 27.5.1-0ubuntu3~24.04.2 amd64 docker.io/noble 24.0.7-0ubuntu4 amd64 雖然版本是跟著官方docker最新版本,但也有持續跳級更新。如果真的要分類,筆者應該會把它歸類為 rolling release。 Rolling release vs Point release 花了一些時間看例子之後,終於開始討論我們自己的更新策略了。rolling release,最主要的原因是,舊版本無人再免費維護了,有什麼bug,都在最新版本中修復,但也因此有機會出現不相容的情況。point release,最主要的原因是為了維持極強的穩定和兼容版本,這亦代表,除官方專家出手,否則很難有舊版本的bug fix。 那麼我們有什麼選擇? 有point release,當然跟point release,因為程式不可能天天做調整。除非大家想要新功能再升級版本。 沒有point release,就手動自己選擇hotfix版或小版本升級。在升級大版本前,一定要做整合測試。若追求極致的穩定,升級大版本時就不要原機升級,要另起爐灶,似兩個相對獨立的環境並行過渡。如果有container版本,就用container隔離,一般java等都可以這樣建獨立環境。 沒有point release,也沒有可隔離的並行環境:其實 docker 接近這類。對它應的OS層的存取,雖然可以用VM隔離,但通常都不實際。因為重新安裝OS, 設定外部環境,成本很高。docker 在中 lab 並行升級是可以,但投産環境並行真的不實際。沒有辦法之下,筆者還是原機升級。頂多是lab中實現更多的整合測試。

Coding中的AI輔能3 | AI 探索新領域
科技新知
MacauYeah・2026-01-26

繼之前筆者介紹使用AI Chat問一些技術固有問題後,筆者亦試著繼續用AI做一些其他功能探索。 也是先講結論 目前筆者針對自己不熟悉的技術,而且認為已存在,不太可能不存在的技術,叫AI幫忙做事。跟過去一期最大的差別,就是筆者無法快速判斷AI的答案是對還是錯,只能跟著AI一句一句的地執行Code再去找問題。但即使是這樣的情況下,AI還是能提供到有參考價值的答案。 Jasper report studio 參數引用 在預設的情況下,Jasper report studio 的某些參數只可以反映在 SQL Data Source中,其他Data Source並不適合。但即使這樣,筆者還是希望AI找尋一下過去的人有什麼解決辦法。原本的問題,筆者在Google上,並不能找到合適的參考案例,但在問Claude Sonnet 後,反而有案例。實測下,也是有效的。 與搜尋引擎關鍵字不同,在Claude Sonnet中,筆者花了較長的字句去描述問題。也有可能是因為「生成式」的關係,Claude Sonnet 可以生成更多我沒有見過的關鍵字,從而得到答案。而這個答案,非常大機會並不是出自官方的使用說明中。這種就像坊間的用法,可能升級後會突然無法使用。但至少目前可以解決問題。 QEMU 的教學 筆者一直被逼著試用一些新的cloud image,並非筆者認知的傳統VM使用方法。qemu筆者之前有看過官方教學,但實在太長、太複雜,故筆者就把自己的問題拋給DeepSeek-V3,看看它能不能提供一個可行的指令。 結果是可行的。不過要重提的是,筆者雖然對QEMU不太懂,但至少對Cloud image有些認識,知道Cloud image是如何運作,某些image又可能缺了些什麼。針對性地問DeepSeek-V3一些具體問題,結果還可以接受。也幫忙解決了筆者誤會抄下來的指令。 總結 總括來講,這種方法係加大了筆者可以搜索的範圍,AI亦可以做一些自己的嘗試。省卻了自己閱讀大量文章之後再組合的過程。對於一些自己太熟悉,但是穩定的技術,應該會有可行解。 但如果針對一些很肯定資料來源的問題,筆者還是會選擇使用傳統搜索的方式或以AI找出官方來源,自行到官網查證。Fact Check 資料可信性,原本就是這麼做,也會繼續這樣做。AI會有幻覺,傳統的搜尋答案有部份也是來Stack Overflow等討論區,也是需要進一步自行了解。

想試國産Linux Cloud Image ? 無問題Qemu快速幫到你
科技新知
MacauYeah・2026-01-21

不知道大家最近有沒有在考慮使用國産OS,如果有,大家又是怎樣做初步測試的呢? 筆者之前一直都笨笨的從ISO開始安裝,所以每試不同的版本,都要從零開始。不但重複,OS安裝階段的複制過程也是很耗時的。但其實國産OS,大部份都有qcow2的格式,我們若只是本地測試的話,其實可以利用qcow2來做快速VM生成。 阿里aliyun 之前筆者有介紹過ubuntu的multipass,若你想試用的國産OS就是阿里aliyun,只要你有ubuntu,就可以快速跑起來。 但如果沒有ubuntu,只要有qemu(多平台),也是可以的。 qemu-system-x86_64 \\ -cpu host -machine type=q35,accel=kvm -m 2048 \\ -nographic \\ -snapshot \\ -netdev id=net00,type=user,hostfwd=tcp::2222-:22 \\ -device virtio-net-pci,netdev=net00 \\ -drive if=virtio,format=qcow2,file=aliyun_3_x64_20G_nocloud_alibase_20251215.qcow2 \\ -drive if=virtio,format=raw,file=seed.img 上述指令中的qcow2和seed.img,階為官方網站可以下載的。預設帳號 alinux 密碼 aliyun。 seed.img是用於cloud-init的,就是初始化VM所用。第二次開機時,就不需要再使用seed.img qemu-system-x86_64 \\ -cpu host -machine type=q35,accel=kvm -m 2048 \\ -nographic \\ -snapshot \\ -netdev id=net00,type=user,hostfwd=tcp::2222-:22 \\ -device virtio-net-pci,netdev=net00 \\ -drive if=virtio,format=qcow2,file=aliyun_3_x64_20G_nocloud_alibase_20251215.qcow2 華為OpenEuler 同樣地,我們也是用qemu可以跑起OpenEuler,只是它沒有seed.img(不支持cloud init),所以直接跑起就好。 qemu-system-x86_64 \\ -cpu host -machine type=q35,accel=kvm -m 2048 \\ -nographic \\ -netdev id=net00,type=user,hostfwd=tcp::2222-:22 \\ -device virtio-net-pci,netdev=net00 \\ -drive if=virtio,format=qcow2,file=openEuler-24.03-LTS-SP3-x86_64.qcow2 預設帳號 root 密碼 openEuler12#$ 第二次開機,指令也是一樣。 龙蜥AnolisOS 方式也一樣。 qemu-system-x86_64 \\ -cpu host -machine type=q35,accel=kvm -m 2048 \\ -nographic \\ -netdev id=net00,type=user,hostfwd=tcp::2222-:22 \\ -device virtio-net-pci,netdev=net00 \\ -drive if=virtio,format=qcow2,file=AnolisOS-8.10-x86_64-ANCK.qcow2 預設帳號 anuser 密碼 anolisos 總結 如果只是要體驗一下國産OS,Qemu快速起VM就足夠。但Qemu本身只有NAT網絡,想要做VM之間的通訊,需要大量的學習成本。

Coding中的AI輔能2 | Ai 寫測試用例
科技新知
MacauYeah・2026-01-21

繼之前筆者介紹使用AI Chat問一些技術問題後,筆者亦試著用AI直接參考code的改動。 先講結論 目前筆者只針對自己熟悉的技術,叫AI幫忙做事。那怕它做錯,我也有條件驗證及修正。而結果是,。 優點:它的確有幫上忙,省了我一些時間。省時不多,但有省得不多。總比全人力Google來得舒服。 缺點:很慢,有點鈍。它的答案也可能很直觀,需要手動再調整。 寫測試 為免一下子挑戰太大,筆者先從寫測試開始。使用一個現有的專案,去掉secret等敏感資訊,然後針對新做的function,叫GitHub Copilot 幫忙寫Test Case。Copilot Agent就會開始檢驗你現有的測試,學著你之前的風格,為新的function寫測試。Copilot會結合你現有的程式,也了解一些框架的知識,例如Hibernate Entity, Repository之間的關係,試著寫一個符合你剛才文字表述的邏輯。就是因為這也是一個整體掃瞄和學習的過程,筆者覺得不論付費還是免費的AI額度,可能都會一樣慢。 為什麼要在這個地方上使用AI幫忙呢? 因為Test Case中,通常因應不同的情況,有不同的預設值。很多時,Test Case相似,又無法直接覆用預設值。所以找AI幫忙起草,後期自己再修正一些,總比全力自己設計要省心一點。 Maven pom依賴升級 筆者亦都有試過找GitHub Copilot 解決一些因版本升級帶來的依賴不相容的問題。同樣地,筆者對於這些問題,有一定的了解,只是不想每個版本逐個比較。筆者想靠 Agent 找到相近或相容的版本,結果算做得不錯。這些問題本身沒有難到需要大量Google去做資料搜集,但至少Troubleshoot時,要回憶幾個不同的maven指令。平常pom 版本分析的指令很少機會會用,一時三刻要重新好好理解一下,也是費神。這個場境,似乎AI也勝任,自己最後驗證也簡單。就像解一元多次方程式一樣,找解很費神,但驗證就很簡單。那怕驗證時真要追蹤 pom file,也有IDE幫忙。 總括來講,筆者沒有叫AI大量創作,在控制問題範圍的情況下,免費額度的GitHub Copilot也能找到一些幫助。

Ubuntu 的簡易日常更新
科技新知
MacauYeah・2025-12-17

早陣子跟新認識的朋友聊天,聽到他們因為要轉伺服器平台,煩惱如何做作業系統層面的定期更新。筆者亦都分享一下自己是如何做 Ubuntu OS 層面的定期維護。 沒錢,就用最原始的方式解決 因為Ubuntu也算是常見的linux品牌,所以基本有有商用軟件可以偵測OS的狀態,並針對它推送更新。不過如果你像筆者一樣,是個貧窮的革命家,那就只有土炮一點自己做鏡像點及做測試。 建立一個 ubuntu 的 deb 包 mirror。手動單次地用步 mirror,確保自己其他 server 同一個時間段都只會取得同一個更新。 停了 ubuntu 的 kernal 自動更新。不然的話,mirror 有更新,ubuntu 亦會偷偷地自動安裝了新的kernal,只是等待你的重啟。 使用一個測試機,先經 mirror 更新到最新的狀態。運行一段日子後,其他機再陸續更新。如果你投産環境有多於一種配置,就考慮要多個不同的測試機。更新指令直接做成 script,方便在其他機器中重複。 輪流 ssh 登入各台機,執行相同的更新指令。更新指令經 git 同步到其他機器。為確保不受 ssh 斷線的風除,必要時還需加入 tmux 。 多機器的煩惱 上述的做法雖然可行,不過當你有十台以上的機器,重複做 ssh, tmux, git checkout, script 互動,也是很累人。考慮一次性地全自動化執行,還是有必要的。筆者對上述的第四步驟,作出一些取捨,以確保更新速度足夠快,可以順暢地執行。 什麼是必需要更新的? 筆者觀察到,在 container 技術出現後,其實很多時安裝應用都不會直接在 OS 層安裝 deb / rpm 包,都是直接經 docker image 去做。所以OS層面,或者很多服務都不會被啟動。筆者亦發現,至少在ubuntu下,只更新kernel,對比無腦全更新所有 deb 包,會快很多很多。 如果可以,我們只更新kernel,再加對應的 container runtime,是不是更新對令相對地穩定,而且可以經外部統一管理。也就是不用在每一台機中進行 tmux + git checkout ,全數在外部推送 ssh 指令? 筆者就用 multipass VM + ssh key,表達一下執行概念。 ssh -i /var/snap/multipass/common/data/multipassd/ssh-keys/id_rsa ubuntu@10.115.189.200 -- apt-get autoremove -y ssh -i /var/snap/multipass/common/data/multipassd/ssh-keys/id_rsa ubuntu@10.115.189.200 -- apt-get update ssh -i /var/snap/multipass/common/data/multipassd/ssh-keys/id_rsa ubuntu@10.115.189.200 -- apt-get install -y linux-generic linux-headers-generic linux-image-generic ssh -i /var/snap/multipass/common/data/multipassd/ssh-keys/id_rsa ubuntu@10.115.189.200 -- reboot 上述最大的假設,是第一、三步,更新 kernel 時不會因為網絡問題導致 ssh 斷線,因為它們都是系統級別的改寫,中斷後並不能確保可以重來。第二步就很安全,隨時重來也沒有問題。 這樣,我們就可以在任一台管理機,經過一個 shell script for loop,更新所有其他機器。 如果我們對於網絡還是有些疑慮,我們也可以試用一次性排程式的方式去做。 ssh -i /var/snap/multipass/common/data/multipassd/ssh-keys/id_rsa ubuntu@10.115.189.200 echo '/your/script/location' | at 08:00 PM 17.12.2025 這樣的好處是,我們可以連 tmux 的開啟也省略,git checkout 也可以經固定的 script 執行(只是很煩鎖)。但這也會有壞處,就是看不到執行的情況,只能事後檢查系統狀態,是否已更新過。 當然前述 ssh key 的方法也可以加入 git checkout 更加深化不同的更新 script,但這又會增大斷線可能。ssh key 還是以快速完成指令更實際。 註:因為網安原因,筆者把上述 script 中的 S U D O 關鍵字去掉,這樣 blog 才能發出。

你開始寫 Spring Boot 測試案例了嗎?
科技新知
MacauYeah・2025-11-29

雖然筆者過往做 spring boot framework 教學中,都有滲入一些測試用例。筆者也曾經困惑了很長一段時間,所以就獨立開一個主題,聊一下筆者在實務上對spring boot test 的理解。 測試案例究竟測試什麼? 測試用例 (test case) 是確保你的程式碼正確性與穩定性的重要步驟,但在 framework 下,並不是所有功能都很容易寫成測試。所以在討論 framework 測試之前,釐清測試的本質。 function input - business logic - function output 這意味著我們輸入某些資料(input),然後經過業務邏輯(business logic)的處理,最後產生結果輸出(output)。 我們的測試目標,其實就是確保業務邏輯正確。而我們的手段就是經檢查概定的輸入資料,核對輸出結果。 那麼只要我們可以生成輸入資料,就一定可以檢查輸出結果了吧?其實不是的,因為實務上的輸入和輸出沒有這麼簡單。筆者常接觸到的輸入輸出如下 輸入 function 輸入參數 系統狀態資料,例如:資料庫狀態、外部API結果。 輸出 function 輸出參數 寫入系統(影響到)的資料,例如:資料庫狀態、使用外部API時的輸入參數。 總之就是考慮了狀態機 (state machine) 的問題,每個狀態+外部輸入都是一個測試用例,然後核對狀態機去了下一個什麼狀態。 言下之意,我們就是暴力地生成輸入參數和模擬狀態資料,道理上就是可以進行測試。 Spring boot web framework 中,我們又會測試什麼? function input - business logic - function output在Spring boot web就變成如下 controller request - business logic - controller response在 Spring Boot test 中,我們可以用模擬的 MVC (MockMvc) 測試來驗證 controller 的行為。不過,其實進入 controller 前經過很多系統轉換,而這些道理上跟Framework的技術大相關,與業務邏輯小相關。所以為免折磨自己,可以將業務邏輯單獨封裝成服務(service)。之後直接測試服務 ,易寫也易讀。 controller request - service input - business logic - service output - controller response道理上 controller 能做的業務邏輯,服務 (service) 都可以無腦重現。這樣還可以重用服務,減少測試的數量。 如何實現輸入? 直接 new Object。大部份的情況下,因為業務是自己編寫的,應該都可以直接 new 出來。 經 json 檔讀入。如果輸入的參數量太多,逐個經 java new 是很耗時的,我們可以經 json 反序列化變成 Object。但這亦只限於自己可以操作/改寫的類。 Mockito 模擬那些無法簡易經 new 或 json 反序列化的 Object。例如:spring security authentication object 我們在使用時,其實只看到 interface。我們難似自己實現一個可以反序列化的類,那麼我們可以使用 Mockito 來模擬這些資料。一些外部API的結果,我們也可以用使 Mockito 來模擬。 什麼情況下不進行測試? 有些情況下,我們可能選擇不對某些功能進行測試,原因可能包括對功能的了解不足或是單純的懶惰。以下是一些例子: 僅進行配置的Function:如果你的 Function 只是在 Framework 中填寫配置,而且你並不太了解它的運作原理,可能就不需要進行測試了。例如,Spring boot web 中,需要大家配置一個SecurityFilterChain Object,它要求大家將 HttpSecurity 轉換為 SecurityFilterChain 。因為輸入的 HttpSecurity 是系統固定的參數,我們亦沒有檢查它的狀態。這種情況下,它的輸入及輸出,其實我們都沒有真正理解。我們硬測試的話,測試功能可能只流於表面。若我們真的要做測試,也是經過MockMvc進行端到端測試(end-to-end testing),測試它在事後的影響範圍。 單純的框架功能:例如資料庫的儲存庫介面(repository interface),雖然是在框架下生成的,對於自己手動調整的部份功能,筆者通常亦不會進行單獨測試,通常都會搭配業務邏輯一起進行。它可以使用 Mockito 進行模擬測試,或用測試環境的真實資料庫進行測試。 面對的挑戰 總括來講,筆者盡可能地把測試用例限定在業務邏輯中,就可以大大地降低寫測試的技術難度。但筆者還是有些問題並未完美解決。 測試用例的數量可能很多,因此共用與維護變得相當困難。逐個用例獨立編寫輸入也是很累的。對於 Mockito 的使用,筆者還是可免則免。因為要逐個功能模擬,編寫量就指數提高,這亦難似配合外部變化。一般來說,能優先使用測試環境或者 Docker 來模擬環境的,就盡量用。 離線開發、離線測試。系統依懶的外部功能越多,想做單機開發的難度就越高。即使前述有 Docker 測試,對於持續整合(CI)來講也是有一定難度。那麼這時,Mockito 就是一個可取的選擇。但這又回到編寫量及難以偵測外部變化問題。 希望這篇文章能幫助你更好地理解測試案例的編寫方向,並在Spring boot web開發中加入你自己的測試!

docker swarm 回到最基礎的群集組建
科技新知
MacauYeah・2025-11-21

雖然筆者都知道,全世界在講 k8s ,全世界都叫筆者放棄 docker swarm,但無獨有偶,docker swarm 還是有使用的價值。 你只有單個服務在運行,只想要做冗餘或分流。快速地用 docker swarm 做最小可行性産品,推出市場。 傳統的HA功能做到了,但你沒有中央匯整日誌的功能。而你也不想把事情攪得太複雜,使用docker swarm 可以讓你在任何一個管理節點上查看不同 container 的日誌。 你的客戶只提供VM,他可能有自己的k8s平台,但不讓你使用。自建一套docker swarm ,先入場,事後擴展再要求客戶提供k8s,對於客戶來講,先證明系統是有價值的,在金錢成本上或能力上,一定是件比較可以接受的事。 筆者之前介紹過一系列的 docker swarm 教學,但生成群集的部份一直沒有做介紹。因為實在太簡單,所以一直都沒有收納在教學內容當中。但現在考慮其完整性,以及為了讓大家感受一下它有多簡單,所以重新寫了組建群集的步驟。 組成群集 以前各家不同的軟件,想要起一個群集,要左攪右攪,又要重啟。而docker swarm真的很簡單,只要各機中有 docker ,再在各機中順序打指令就好。 node 1 使用docker swarm init docker swarm join-token manager # node 1 > docker swarm init > docker swarm join-token manager To add a manager to this swarm, run the following command: docker swarm join --token SWMTKN-1-xxxxxxxxxxxxxxxxxxxxxxx xxx.xxx.xxx.xxx:2377 其餘的管理員節點就根據上述的提示,使用 docker swarm join --token SWMTKN-1-xxxxxxxxxxxxxxxxxxxxxxx xxx.xxx.xxx.xxx:2377 就好。只要總數的管理員節點有奇數個就可以了(包括當初的node 1)。即是1、3、5等都可以。這是因為在容錯的情況下,必需由管理節點作出多數決,才能容易地知道判斷是哪些節點出現問題。 如果不為容錯,只想增加可工作的機器,那麼我們只需要增加工作節點。我們可以在任何管理員節點生成docker swarm join-token worker > docker swarm join-token worker To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-yyyyyyyyyyyyyyyyyyyyyyy yyy.yyy.yyy.yyy:2377 若想要檢查各個節點的工作狀態,在管理員節點上執行 docker node ls 看到了。 docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION xxxxxxxxxxxxxxxxxxxxxxxxx * node1hostname Ready Active Leader 28.5.1 yyyyyyyyyyyyyyyyyyyyyyyyy * node2hostname Ready Active Reachable 28.5.1 全部教學請見 https://macauyeah.github.io/AProgrammerPrepares/VMDockerNotes/SwarmModeCommandCN.html