自由學習的風

幽夢影 張潮 少年讀書,如隙中窺月;中年讀書,如庭中望月;老年讀書,如臺上玩月。皆以閱歷之淺深,為所得之淺深耳。

Linux:批次設定檔案/目錄 權限及擁有者

2026年8月17日 星期一

在管理 Linux 伺服器(特別是架設 WordPress 或網站)時,常常會遇到檔案權限混亂,導致網頁出現「403 Forbidden」或是無法上傳圖片的狀況。

如果直接使用 chmod -R 755 *,會不小心把不需要執行的普通檔案也變成可執行檔,造成安全漏洞。最標準的做法是:將目錄設為 755,檔案設為 644。本文分享如何利用 find 指令高效完成權限與擁有者的批次設定。


一、 核心指令:分開設定目錄與檔案權限

請將指令中的 /your/path 替換成你實際的資料夾路徑(例如:/var/www/html)。如果你已經在該目錄下,可以直接用 . 代替路徑。

1. 將所有目錄(資料夾)設為 755

sudo find /your/path -type d -exec chmod 755 {} +
  • -type d:指定只尋找「目錄(Directory)」。
  • 755 權限:擁有者可讀寫執行(rwx),其他人可讀取與進入(r-x)。資料夾必須有執行權限(x)大家才能進得去。

2. 將所有檔案設為 644

sudo find /your/path -type f -exec chmod 644 {} +
  • -type f:指定只尋找「一般檔案(File)」。
  • 644 權限:擁有者可讀寫(rw-),其他人只能讀取(r--),大家都沒有執行權限,確保系統安全。

二、 進階補強:變更檔案擁有者(chown)

調整完權限後,如果網站還是無法運作,通常是「擁有者(Owner)」錯了。例如 Apache 或 Nginx 網頁伺服器通常使用 www-data 這個用戶。

1. 變更整個資料夾的擁有者與群組

sudo chown -R www-data:www-data /your/path
  • -R:代表遞迴(Recursive),會連同子目錄、檔案一起修改。
  • www-data:www-data:冒號前面是「新用戶」,後面是「新群組」。

2. 唯獨針對「特定舊用戶」的檔案進行轉移

如果你只想把原本屬於 olduser 的檔案找出來並改成 newuser,可以結合 find 指令:

sudo find /your/path -user olduser -exec chown newuser {} +

💡 關鍵語法解析:末尾的 {} + 是什麼意思?

這是在 Linux 中提升效能的進階技巧。它們必須搭配 -exec 參數一起看:

  • {} (佔位符):代表 find 實際找到的每一個檔案路徑。
  • + (批次打包):通知電腦把所有找到的檔案「打包成一長列」,只呼叫 1 次 chmodchown 指令來處理。

比起傳統使用 \; 結尾(找到 1000 個檔案就會執行指令 1000 次),使用 + 的速度會快上數十倍,非常適合在檔案量龐大的伺服器上使用!

[AIgen] 機器掛了,只有Linux映像檔,如何找回定時執行的設定?

2026年8月10日 星期一

當伺服器突然崩潰、無法正常開機,而你手邊只剩下一份 Linux 系統映像檔(Image),或者是好不容易將硬碟掛載(Mount)到臨時系統的 /mnt/lvm 目錄時,身為維運或開發人員的你,該如何拯救那些珍貴的 Crontab 定時排程設定?

在正常的 Linux 環境下,我們習慣直接輸入 crontab -l 來查看排程。然而,在目前只有掛載目錄、沒有開機的狀態下,因為背景服務(Cron Daemon)根本沒有執行,這個指令是完全無法運作的。

這時候,我們必須跳過指令,直接深入映像檔的結構。本文將帶你手把手透過三個方向,直接去 /mnt/lvm 底下把所有遺失的定時設定挖出來!


方法一:直擊使用者排程(User Crontabs)

在 Linux 系統中,所有個別使用者(包含 root 帳號)自行透過 crontab -e 建立的排程,本質上都是一個獨立的文字檔,並以「使用者名稱」作為檔名儲存在特定的緩衝目錄中。

既然映像檔已經掛載在 /mnt/lvm,我們可以直接查看底下的對應路徑:

🔍 檢索步驟:

1. 列出所有擁有排程的使用者:

ls -la /mnt/lvm/var/spool/cron/crontabs/

2. 直接查看該使用者的排程內容:

cat /mnt/lvm/var/spool/cron/crontabs/[使用者名稱]

*(例如:欲查看 root 的排程,請輸入 cat /mnt/lvm/var/spool/cron/crontabs/root)*


方法二:地毯式搜尋系統級排程(System-wide Crontabs)

如果你的排程當初是交由系統全域執行,或是由特定軟體套件自動建立的,它們通常不會出現在上述的使用者目錄中,而是散落在系統設定的 /etc 目錄內。

請依序檢查 /mnt/lvm 底下的這四個關鍵位置:

  • 📁 主要核心設定檔: 這是系統最基礎的排程表。
    cat /mnt/lvm/etc/crontab
  • 📁 獨立套件排程目錄: 許多第三方軟體(如自動備份工具、安全防護套件)會將排程獨立寫成檔案放在這裡。
    ls -la /mnt/lvm/etc/cron.d/
  • 📁 週期性執行腳本目錄: 檢查系統預設的週期性資料夾,裡面通常放著直接被定時觸發的 Shell Script(腳本檔)。
    • /mnt/lvm/etc/cron.hourly/ (每小時執行)
    • /mnt/lvm/etc/cron.daily/ (每天執行)
    • /mnt/lvm/etc/cron.weekly/ (每週執行)
    • /mnt/lvm/etc/cron.monthly/ (每月執行)

方法三:終極大絕!從系統日誌(Logs)逆向重建

如果最糟糕的情況發生了——定時排程的檔案已經損毀,或者你在上述目錄完全找不到紀錄,我們還有一招隱藏版技巧:從舊系統過去的執行紀錄中逆向推敲。

只要該排程在機器掛掉前曾經執行過,Linux 的日誌系統就會留下足跡。我們可以透過分析舊系統的日誌,查出過去「什麼時間點」執行了「什麼指令」,進而重新拼湊出原本的 Crontab 設定。

🔍 逆向追蹤指令:

grep -i cron /mnt/lvm/var/log/syslog

*(註:視舊系統的 Linux 版本與環境不同,部分舊系統或特定發行版的紀錄可能會儲存在 /mnt/lvm/var/log/cron 檔案中。)*


💡 進階技巧:直接切換環境執行

如果你覺得路徑一直加 /mnt/lvm/ 很麻煩,或者你想直接在該映像檔環境下執行其他需要環境變數的救援指令,你可以利用 chroot 工具,把目前終端機的根目錄直接「切換」進去:

sudo chroot /mnt/lvm

切換成功後,你就可以直接輸入 crontab -l(此時讀取的就是映像檔內的排程),或是直接用正常的 /etc/crontab 路徑進行操作囉!

希望這篇文章能幫各位在伺服器災難復原時,快速找回遺失的自動化排程!

[AIgen] MariaDB 生產環境怎麼選?從 10.11、11.4 到 12.3 LTS 的升級風險與最佳路徑指南

在維護企業級或個人專案的資料庫時,選擇一個穩定、支援週期長的 LTS(長期支援) 版本是至關重要的決定。隨著 MariaDB 官方近年架構更動頻繁,許多仍停留在經典版本(如 10.11 LTS)的維運人員,正面臨是否該升級、該跳到哪一個世代的交叉路口。

本文將為你梳理目前主流的 MariaDB LTS 版本特點,並深度解析跨代升級(10 LTS 升級到 11 或 12 LTS)的潛在風險與安全路徑,幫你的資料庫無痛續命!


📌 一張表看懂現行 MariaDB LTS 版本現況

MariaDB 官方針對生產環境提供了不同的長期支援版本。以下是目前市面上最主要的四大 LTS 選擇:

  • MariaDB 10.11 LTS (經典穩健):廣泛使用的舊世代穩定版本,支援至 2028 年 2 月
  • MariaDB 11.4 LTS (目前主力推薦):穩定可靠的長期維護版本,也是目前的黃金升級目標,支援至 2029 年 5 月
  • MariaDB 11.8 LTS (過渡型 LTS):包含向量搜尋與複製效能增強的年度 LTS 版本,支援至 2028 年 6 月
  • MariaDB 12.3 LTS (最新世代):最新推出的長期支援版本,提供優化的向量搜尋與極佳的寫入效能。

🛑 大跨代升級:從 10 LTS 直升 12 LTS 有哪些風險?

如果你的資料庫目前處於 10.11 LTS,想要一步到位直接升級到 12.3 LTS官方非常不建議這樣做,因為這屬於跨越兩個大版本的重大變更,具備相當高的風險!

直接跨代硬幹,最容易遇到以下三大核心問題:

  1. 隔離級別預設值變更(Behavior Change)
    在 12.3 LTS 中,innodb_snapshot_isolation 的預設值改成了 ON(旨在讓 REPEATABLE READ 的行為更精確)。這可能會改變你既有應用程式的交易(Transaction)鎖定行為,必須實測確認。
  2. 查詢優化器(Optimizer)行為劇變
    11.x 世代對優化器进行了大量重構,全面調整了成本估算模型。部分在舊版 10.x 跑得很快的複雜 SQL 語法,在 12.x 可能因為成本估算模型改變而突然變慢,產生效能退化(Regressions)。
  3. 廢棄參數與套件依賴衝突
    10.11 的許多舊 my.cnf 參數在 12.x 已被移除,直接沿用可能導致資料庫無法啟動。另外,若有使用 Galera Cluster,12.3 起已移除自動依賴,必須手動補裝 mariadb-server-galera,否則叢集會直接無法同步。
⚠️ 官方推薦的安全路徑:必須採兩階段升級。先從 10.11 LTS 升級至 11.4 LTS 並執行結構更新,確認穩定後,再從 11.4 LTS 升級至 12.3 LTS。

💡 折衷方案:如果只升級到 11.4 LTS 呢?

相較於直奔 12 LTS,選擇升級到 11.4 LTS 是目前風險顯著降低、且最為穩健的策略

從 10.11 到 11.4 是一條官方標準支援的直升路徑,不需要多階段過渡。不過,11.4 畢竟也是重大升級(Major Upgrade),你仍需留意以下轉變:

  • 優化器成本模型調整:雖然 11.x 的新優化器對大部分查詢都有利,但極少數複雜的 JOIN 或特定索引查詢仍可能誤判。
  • 徹底移除 InnoDB Change Buffer:為了簡化代碼並提升現代 SSD 的寫入穩定性,11.0 起已移除此快取。如果應用程式有極大量的「隨機非聚集索引寫入」,可能會觀察到磁碟 I/O 壓力些微上升。
  • 一樣不可逆向降級:11.4 使用了全新的 InnoDB 檔案格式與 Redo Log 架構。一旦升級並更新系統表,資料檔案將永久無法退回 10.11 讀取

📊 升級終極對決:11.4 LTS vs 12.3 LTS

評估維度 升級至 11.4 LTS 升級至 12.3 LTS
路徑複雜度 🟢 (可直接從 10.11 覆蓋升級) 🔴 (需先過渡到 11.4,進行兩次升級)
隔離級別行為 🟢 無變更(維持既有鎖定邏輯) 🟡 有變更innodb_snapshot_isolation 預設開啟)
Galera 套件結構 🟢 維持原樣 🟡 結構拆分(需手動補裝 Galera 套件)
生產環境建議度 極高(目前最推薦的穩定長效版本) 🔵 (適合需要最新向量搜尋特性的團隊)

🛠️ 維運人員的「防踩雷」升級準備

不論你最後決定升級到 11.4 還是 12.3,在動手更新 production 環境前,請務必嚴格執行以下三件事:

  1. 乾淨關閉(Clean Shutdown):升級前關閉服務時,務必確認 innodb_fast_shutdown 不可設定為 2(不可強制崩潰關閉),以確保 Redo Log 完全清空、資料全面落盤,否則新版二進位檔案可能無法讀取舊日誌。
  2. 完整的物理與邏輯備份:升級失敗是無法直接降級的!請務必使用 MariaDB Backup 進行完整物理備份,並針對 mysql 系統資料庫進行 mariadb-dump 備份。
  3. 搭建 Staging 環境盲測:強烈建議匯入一份真實資料到測試機,模擬升級流程,並將後端應用的壓測腳本導過去跑一次,觀察有沒有噴任何 SQL 語法錯誤或效能嚴重下滑的現象。

結語

如果你的專案沒有迫切需要 12.x 的新功能(例如最新版的向量搜尋優化),現階段將舊環境升級到 11.4 LTS 是投資報酬率最高、也最安全的選擇。它不僅能避開 12.x 許多行為改變的風險,還能穩定地將你的資料庫安全生命週期一口氣延長到 2029 年。

Laravel 排程在 Docker 中執行

2026年7月28日 星期二

Laravel 專案有排程要執行,但是 php-fpm container 裡沒有 crontab 指令,這是很常見的情況。

這時候不要急著把 cron 裝進 php-fpm。php-fpm 本來是處理網站 request 的,排程可以用別的方式做。

需求:

要定時執行:

php artisan forum:sync

例如每天 4 點和 15 點各執行一次。

方法一:由 Linux 主機 crontab 執行

可以直接在 host 的 crontab 裡呼叫 container 裡的 artisan:

docker exec -w /var/www/default php-fpm php artisan forum:sync

先手動測一次:

docker exec -w /var/www/default php-fpm php artisan forum:sync

如果可以正常執行,再加入 crontab:

crontab -e

每天 04:00 和 15:00 執行:

0 4,15 * * * /usr/bin/flock -n /tmp/forum-sync.lock /usr/bin/docker exec -w /var/www/default php-fpm php artisan forum:sync >> /var/log/forum-sync.log 2>&1

指令說明:

  1. 0 4,15 * * *

每天 4 點和 15 點執行。

  1. /usr/bin/flock -n /tmp/forum-sync.lock

避免上一輪還沒跑完,下一輪又啟動。

  1. /usr/bin/docker exec

從 host 執行 container 裡的指令。

  1. -w /var/www/default

指定 Laravel 專案所在目錄。

  1. >> /var/log/forum-sync.log 2>&1

把執行結果和錯誤訊息寫入 log。

方法二:建立 scheduler container

如果想比較 Docker 化,也可以另外建立一個 scheduler service:

laravel-scheduler:
  image: "${PHP_VERSION}"
  container_name: laravel-scheduler
  working_dir: /var/www/default
  volumes:
    - ./wwwroot:/var/www
    - ./session:/var/lib/php/session
  environment:
    TZ: ${TZ}
  command: sh -c "while true; do php artisan schedule:run --verbose --no-interaction; sleep 60; done"
  restart: unless-stopped
  depends_on:
    - mysql

啟動:

docker compose up -d laravel-scheduler

這種方式適合有使用 Laravel scheduler,也就是在 app/Console/Kernel.php 裡集中管理排程的專案。

常見錯誤:

如果出現:

Could not open input file: artisan

代表 -w /var/www/default 不是 Laravel 專案所在目錄,要改成實際路徑。

如果實際使用 PHP 8.3 container,就要把 container 名稱改成:

php83-fpm

結論:

php-fpm 裡沒有 crontab 不算問題。

簡單需求可以用 host crontab 呼叫:

docker exec ...

比較完整的 Laravel 排程,則可以用獨立 scheduler container。

不要把所有功能都塞進 php-fpm,之後比較好維護。

PHP-FPM Docker image 選擇與重建


最近整理 PHP-FPM 的 Dockerfile,順便把 PHP 8.4、PHP 8.2、PHP 8.3、PHP 7.4 的 image 選擇記錄一下。

PHP 8.4 要選哪一個?

如果是一般 Laravel、Symfony、WordPress 或自己寫的 PHP 網站,建議先用:

FROM php:8.4-fpm

如果想更明確,可以寫:

FROM php:8.4-fpm-trixie

Debian-based image 比較適合一般網站環境,extension 和系統套件比較不容易踩到奇怪的相容性問題。

Alpine base 呢?

Alpine image 比較小,例如:

FROM php:8.4-fpm-alpine

但 Alpine 使用 musl libc,有時 PHP extension、Composer package 或外部 binary 會比較麻煩。

除非真的很在意 image 大小,不然一般網站我會先選 Debian 版。

不建議用 buster

buster 是比較舊的 Debian 系列,不建議再拿來當新的 PHP 8.4 image 基礎。

如果要固定 Debian 版本,可以考慮:

FROM php:8.4-fpm-trixie

或依需求使用 bookworm 系列。

官方 image 更新後要重新 build

如果官方 php:8.4-fpm 有更新,本機自建 image 不會自己變新。

要重新 build,建議加上 --pull:

docker build --pull -f Dockerfile_php84-fpm -t tiebob/php:8.4-fpm .

如果用 Compose:

docker compose build --pull
docker compose up -d

如果想完全不用 cache:

docker compose build --pull --no-cache

Dockerfile 整理重點:

這次整理 Dockerfile 時,主要做了幾件事:

  1. 明確指定 base image
  2. apt-get update、apt-get install、清 cache 放在同一層
  3. 加上 --no-install-recommends
  4. 移除 production image 不必要的 vim
  5. Composer 改成從官方 image 複製

Composer 可以這樣裝:

COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer

這樣比在 Dockerfile 裡 curl installer 清楚一些。

PHP 7.4:

後來也建立了 PHP 7.4 的 Dockerfile:

FROM php:7.4-fpm-bullseye

不過 PHP 7.4 已經是 EOL,只建議給舊系統短期使用,不適合新的正式服務。

所以如果專案裡還有 PHP 7.4,最好在檔案裡加註解,提醒自己這是 legacy 用途。

結論:

我的選擇大概是:

一般網站:php:8.4-fpm 或 php:8.4-fpm-trixie
想省 image 大小:php:8.4-fpm-alpine
舊系統相容:php:7.4-fpm-bullseye,但要標示風險

Image 不一定要追最新,但版本和用途要寫清楚,之後維護才不會搞混。

Docker container 的 UID/GID 權限整理

示意圖:Docker UID/GID 權限關係


這次整理 Docker 多網站環境時,遇到一個很常見的問題:不同 container 裡的使用者 UID/GID 不一樣,結果 bind mount 到 host 的檔案權限就容易亂掉。

問題:

目前有這些服務:

  1. nginx
  2. php-fpm
  3. php82-fpm
  4. php83-fpm
  5. mysql

PHP-FPM 大多已經是:

uid=1000(www) gid=1000(www)

但是 Nginx worker 可能是:

uid=101(nginx) gid=101(nginx)

MySQL 則是自己的:

uid=27(mysql) gid=27(mysql)

這時候如果 PHP 建立檔案、Nginx 要讀檔,或者 host 要直接修改檔案,就可能遇到權限問題。

原則:

不要把所有 container 都硬改成同一個 UID。

應該分成兩類:

網站檔案:
nginx、php-fpm、php82-fpm、php83-fpm

資料庫資料:
mysql

也就是網站相關服務統一,MySQL 保持自己的使用者。

建議目標:

nginx worker -> 1000:1000
php-fpm      -> 1000:1000
php82-fpm    -> 1000:1000
php83-fpm    -> 1000:1000
mysql        -> 保持 mysql 預設 UID/GID

網站目錄可以整理成:

sudo chown -R 1000:1000 ./wwwroot
sudo chown -R 1000:1000 ./session
sudo chown -R 1000:1000 ./log/nginx

MySQL 資料目錄不要一起改。

如果 MySQL container 裡查到是 27:27:

sudo chown -R 27:27 ./data/mysql/data

Nginx 注意事項:

原本以為可以直接在 nginx.conf 寫:

user 1000 1000;

結果啟動時出現:

getpwnam("1000") failed

原因是 Nginx 的 user 指令會去找使用者名稱,不是單純用數字 UID。

比較好的方式是自建 Nginx image,在 image 裡建立一個 www 使用者,UID/GID 是 1000:1000,然後 nginx.conf 寫:

user www www;

驗證:

先讓 PHP 建立測試檔:

docker compose exec php-fpm sh -c 'echo ok > /var/www/permission-test.txt'

再讓 Nginx 讀取:

docker compose exec nginx sh -c 'cat /var/www/permission-test.txt'

回 host 看 owner:

ls -lan ./wwwroot/permission-test.txt

如果看到:

1000 1000

而且 Nginx 也能讀到 ok,表示權限大致整理好了。

結論:

遇到 Docker 權限問題,不要先用:

chmod -R 777

這只是把問題蓋掉。

比較好的做法是先弄清楚誰要讀、誰要寫,再把共同使用同一批檔案的 container 對齊 UID/GID。

Docker 多網站部署架構整理

示意圖:Docker 多網站部署架構








圖片檔 blog-drafts/images

目前在 Linux 主機上利用 Docker 跑多個網站,這次順手把目前的建置方式整理一下,避免之後要調整時又要重新看一次。

環境:

  1. Linux 主機
  2. Docker / Docker Compose
  3. Nginx 或 Caddy 做 Web 入口
  4. 多個 PHP-FPM container
  5. MySQL container

目前架構:

大致上是這樣:

Browser
  ↓
Nginx / Caddy
  ↓
依不同網站轉給不同 PHP-FPM
  ↓
MySQL

這樣的做法有點像把傳統的 LEMP 主機,改成用 Docker 來管理。

目的:

  1. 一台主機可以放多個 PHP 網站
  2. 不同網站可以使用不同 PHP 版本
  3. 網站目錄、log、資料庫資料都放在 host 上,方便備份
  4. Web server 統一處理 80、443、SSL、virtual host
  5. 需要瀏覽器自動化時,可以用 geckodriver container

目前比較像「共享主機 Docker 化」,不是每個網站都獨立一整組服務。

建議調整:

1. 不要使用 latest

例如:

NGINX_VERSION=nginx:latest

建議改成固定版本:

NGINX_VERSION=nginx:1.29.3-alpine

不然之後重新 build 或 pull 時,可能會拉到不同版本,問題會比較不好追。

2. PHP 7.4 要列為舊系統

如果還有網站需要 PHP 7.4,可以先保留,但要知道這已經是 legacy 環境。

建議做法:

  1. 先列出哪些網站還需要 PHP 7.4
  2. 確認不能升級的原因
  3. 有計畫地改到 PHP 8.2 / 8.3 / 8.4

3. MySQL 不一定要開給外部

如果只有 container 裡的網站會連 MySQL,通常不需要:

ports:
  - 3306:3306

比較保守可以改成:

ports:
  - 127.0.0.1:3306:3306

或者乾脆不要 publish port,只讓 Docker network 內部連線。

4. volumes 和 bind mount 要整理

目前像這些目錄都會影響備份:

wwwroot/
data/mysql/data/
etc/nginx/
etc/caddy/
log/
session/

建議之後整理一份備份清單,才不會只備份 image,卻漏掉真正重要的網站資料。

結論:

這個架構是可行的,而且蠻適合維護多個 PHP 網站。

接下來優先處理的順序,我覺得可以是:

  1. 固定 image 版本
  2. 整理 Nginx / PHP-FPM 權限
  3. 收斂 MySQL 對外連線
  4. 補上 healthcheck
  5. 將 PHP 7.4 網站逐步升級
  6. 評估改用 Caddy 簡化 HTTPS

先把基礎整理好,之後要搬主機、重建服務或排除錯誤都會輕鬆很多。

VS Code 直接透過 sftp 同步到遠端伺服器

2024年9月29日 星期日

環境介紹:

  • 正式機:10.x.y.aaa,  Linux Ubuntu + Docker(Nginx + PHP + MySQL)
  • 開發機:10.x.y.bbb, Windows 11 + Laragon + VS Code

之前利用 VS Code 開發之前,總是利用 SSHFS-Win 掛載至本機後,再用比對軟體檢查哪些檔案有修改,是否需要上傳(註:freecommander 很好用)。

不過,有時只是一、二支程式需要上傳,總覺得這樣做的話有點繁瑣,最近發現有支 vscode 的 extension(擴充套件):sftp

可以 ssh 連到遠端伺服器,直接上傳,也支援多個網站,所以可以先上傳到測試伺服器,沒問題後再上傳到正式機。

安裝後要先設定遠端伺器資訊,按【F1】,選擇「SFTP: Config」,會在 .vscode 目錄中產生 sftp.json 設定範本檔,直接依個人需求填入設定值即可。


預設是只會有一組伺服器設定,若有多組伺服器的話,例如有測試機、正式機…等,那就要設定 profiles,把設定檔改成下列即可,連線時,按按【F1】,選擇「SFTP: Set Profile」,選擇要連線的伺服器即可。


這支擴充套件還提供其它蠻方便的功能,也可以去發掘喔!

利用 Docker 快速建立 Sql Server 環境

2023年2月16日 星期四

環境:

  1. Ubuntu Linux 2022
  2. Docker CE 23.0.1

Docker 映像檔:

  • mcr.microsoft.com/mssql/server:2022-latest

操作:

  1. 下載 SQL Server 2022 Image
    $ docker pull mcr.microsoft.com/mssql/server:2022-latest
  2. 執行容器(指定參數)
    $ docker run \
    -e "ACCEPT_EULA=Y" \
    -e "MSSQL_SA_PASSWORD=<YourStrong@Passw0rd>" \
    -p 1433:1433 --name sql1 --hostname sql1 \
    -d \
    mcr.microsoft.com/mssql/server:2022-latest

  3. 檢查容器執行狀態
    $ docker ps  
  4. 安裝成功後,可下載或利用 chocolatey 來安裝 Sql Studio Management Studio
    c:\> choco install sql-server-management-studio
  5. 連線至 SQL Server 容器

容器執行參數說明:

  1. -e ACCEPT_EULA= 同意使用者授權合約
  2. -e MSSQL_SA_PASSWORD=<YourStrong@Passw0rd> 設定 SQL Server 最高管理員 sa 的密碼
  3. --name sql1 設定容器名稱
  4. --hostname sql1 設定容器主機名稱
  5. -p 1433: 1433 設定 port 的對應
  6. -d 設定容器以背景模式執行
  7. mcr.microsoft.com/mssql/server:2022-latest  SQL Server 映像檔來源與名稱

進階:

1. 掛載 volume 保存資料庫內容

  1. host 建立掛載的目錄
    $ mkdir data_mssql
  2. 【必須】設定該目錄擁有者, 預設owner id 為 10001
    $ sudo chown -R 10001 data_mssql
  3. 停止、刪除容器後,加上掛載 volume 參數後重新啟動容器
    $ docker run \
    -e "ACCEPT_EULA=Y" \
    -e "MSSQL_SA_PASSWORD=<YourStrong@Passw0rd>" \
    -p 1433:1433 --name sql1 --hostname sql1 \
    -v ./data_mssql:/var/opt/mssql
    -d \
    mcr.microsoft.com/mssql/server:2022-latest

2. 利用 docker-compose 執行容器

1. 建立 docker-compose.yml 檔案,內容如下:
version: '3.5'

services:
  mssql:
    image: mcr.microsoft.com/mssql/server:2022-latest
    restart: always
    ports:
      - 1433:1433
    volumes:
      - ./data_mssql:/var/opt/mssql
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=PutYourPassword
      - MSSQL_PID=Express
2. 執行

$ docker-compose up -d 


VS Code integreted terminial 的環境變數沒有更新

2023年1月15日 星期日

執行環境:

  • Windows 11 21H2(22000.1042)
  • Laragon 5.0(6.0)
  • VSCode
  • CodeIgniter 4.1.9

在Windows環境上利用 Laragon 來建立 PHP 開發環境十分方便,可以快整切換 PHP 版本,程式撰寫則用  VSCode,本來都沒啥問題,不過,這兩天測試之前建立的 CodeIgniter 4,它的版本是  4.1.9,看官網已經出到  4.3.0,不過需要 PHP 7.4 以上,但是之前都在 PHP 7.3 開發,結果在 Laragon 切換成 PHP 7.4 後,VSCode integreted terminial 顯示的還是  PHP 7.3。

試了下列動作:

  1. 把 VSCode 全部關掉,重新再執行 => 無效
  2. 檢查電腦環境變數,PATH 沒有設定 PHP 路徑
  3. 將 PHP 7.4 路徑加入 PATH 環境變數 => 無效

本來以為是電腦出問題了,後來看到一份資料,需要從終端機直接執行 VSCode,讚!有效,解決了,平時我都是按 Win Key,再直接執行,沒想到執行方式不一樣會造成這種影響。


讀取 空氣品質指標(AQI) 的OpenData 資料

2022年10月15日 星期六

一、前由

前2天有位夥伴反應一個問題,之前讀取線上的 空氣品質指標(AQI) 資料時可以秒開,可是現在已經換成新的網址,結果讀取時間變得得慢,想請教大家有沒有解法。

 1. 空氣品質指標(AQI) 舊網址:http://opendata2.epa.gov.tw/AQI.json

 2. 空氣品質指標(AQI) 新網址:ttps://data.epa.gov.tw/api/v2/aqx_p_432?api_key=e8dd42e6-9b8b-43f8-991e-b3dee723a52d&limit=1000&sort=ImportDate desc&format=JSON

二、測試、找原因

直接用瀏覽器開AQI 舊網址,果然秒開;接著瀏覽器再開新 AQI 網址,心裡默數,回應時間不一定,從6秒~11秒都有,換成 Windows PowerShell終端機,利用 curl 指令來抓取新網址,也是一樣的回應時間。

查了資料,發現新網址是環保署的服務,也有提供 API 的操作手冊,  裡面有提供 filter 來過濾回傳的內容資料,參考操作手冊,直接在網址上加上 filter 的條件,情況還是一樣,而且 filter 條件並沒有作用

不死心,又查了一下資料,有篇文章「MicroPython 空氣品質 AQI 獲取之方式」有提到抓取資料改成要申請 API_KEY、換成 HTTPS 協定,以及利用 filters 的 API 語法來指定查詢的項目。所以我就去申請了一組 API_KEY 準備看看是否正常,唉!無效,還是一樣慢,API 語法也沒有作用……

總覺得不太可能提供給全國查詢的服務會這麼慢,所以直接利用 php 去抓網頁資料,Guess What ?

秒回啊!

三、實作

利用簡單的語法寫了簡單抓不同城市的 AQI 資料,回應速度快,滿意,結案!

<h2>空氣品質指標(AQI)查詢</h2>
<form action="" method="POST">

  <select name="county" id="">
    <option value="新北市">新北市</option>
    <option value="高雄市">高雄市</option>
    <option value="臺北市">臺北市</option>
    <option value="臺中市">臺中市</option>
    <option value="臺南市">臺南市</option>
  </select>

  <input type="submit" value="查詢">

</form>

<?php
if (isset($_POST["county"]) &&  $_POST["county"] != "") {
  $county = $_POST["county"] ?? '新北市';
  $key = 'e8dd42e6-9b8b-43f8-991e-b3dee723a52d';
  $filter = 'county,EQ,' . $county;
  $url = sprintf('https://data.epa.gov.tw/api/v2/aqx_p_432?filters=%s&api_key=%s&format=json', $filter, $key);
  $data =  file_get_contents($url);

  $jsondata = json_decode($data);

  echo ('<h2>' . $county . '</h2>');
  var_dump($jsondata->records);
}


四、後記

後來發現 Windows 底下的 curl  指令有點"不好操控",利用 Linux 環境直接下 curl 指令,回應速度也是秒開。



sr-only 是做什麼用的?

常常在網頁中看到這個屬性,檢視網頁發現不會顯示,好奇查了一下資料,原因它是指「screen reader only」,也就是設計給螢幕閱讀器讀取的屬性,一般的瀏覽器不會顯示,長知識了!


CentOS 7 如何更新 php 版本

2022年4月23日 星期六

 之前利用 Remi 的 Repo 來安裝 php 7.0,現在想把 7.0 更新到 7.4,又不想裝上每個套件都加上後綴 xxx74 這種醜醜的名稱,這時候可以透過修改 Remi 的 Repo 來達成。

yum-config-manager  --enable remi-php74

# yum update

二行指令,搞定!





常用遠端連線程式列表

2022年4月12日 星期二

做個記錄。

連線後可直接接管螢幕畫面:

  •  VNC
  • TeamViewer
  • Anydesk
  • ShowMyPC
  • AweSun
連線後被控端會登出:
  • 遠端桌面連線 (micrsoft)

[系統]隱藏某個Windows 更新項目

2021年4月7日 星期三

 之前在 Windows 7 時代,可以在更新項目中直接選擇將某些更新隱藏起來不更新,結果到了 Windows 10 就把這項功能移除掉了。

本來也沒啥問題,不過,Windows 最近的更新又出包了,我有一台  20H2 一直會更新 KB5000802 這支更新檔,造成反覆更新、反覆開機,上網查了一下,嘿!原來得自己去官網下載程式才提供。

PS: 不過,很奇怪的是…官網搜尋到的下載網址顯示 File Not Found...只能找其它資訊站台 :(



參考文章:Show or Hide Updates Tool will block unwanted Windows Updates in Windows 10
下載網站:Downloading Microsoft Show or Hide Updates Troubleshooter

[Ubuntu] 清除 broken 和 residual package

2021年1月31日 星期日

在 debian/ubuntu/mint  安裝或移除套件時,幾乎都是利用 apt 這支程式來處理。

但是有時候安裝失敗時、或是未完全移除時(--purge),就會有套件變得不完全。

residual package 用  dpkg -l 列出來時,會在開頭出現 rc 的字符,而 broken package  則會在開頭出現 iU 的字符,我們可以用下列的指令來篩選出來:

dpkg -l |grep "^rc" 

dpkg -l |grep "^iU"








我們可以下達 apt purge [package name] 的指令來徹底移除它,不過,如果類似的套件很多,就是件折磨人的事了,不過,linux 的好處就可以自己隨意組合指令來符合自己的需求,搭配 awk 把套件名稱撈出來,再丟給 apt 來移除,方便又省事!

sudo apt purge $(dpkg -l |grep "^rc" | awk '{print $2}')

[Ubuntu] 單網卡綁多個網段的IP

2021年1月19日 星期二

[php] 學生作業系統 - 評分便利篇

2021年1月11日 星期一

目標:

  1. 作品圖片可以一列多個作品。
  2. 作品存取日期在一周內會顯示顯目底色。

[C#] 有趣的截圖方式

2021年1月10日 星期日

 截圖的方式有好幾種,這一篇文章是我看到的有趣又簡潔的一種方式 - 模擬使用者按[print screen] 按鈕的方式來做截圖,Interesting!!!

      this.Hide();            

            System.Threading.Thread.Sleep(1000);

            SendKeys.Send("{PRTSC}");

            Image myImage = Clipboard.GetImage();

            pictureBox1.Image = myImage;

            

            myImage.Save("E:\\abc.jpg");

            this.Show();

        }

[Share] How to Install WCMP (Windows, Caddy, MySQL and PHP) Manually

2020年12月31日 星期四