☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
iot 初學

Web Kiosk 模式完整指南

什麼是 Kiosk 模式?

💡 比喻:把瀏覽器變成專用電視 你家的電視只能看電視節目,不能拿來上網、玩遊戲。 Kiosk 模式就是把一台電腦「鎖」成只能顯示一個網頁, 就像把一台電腦變成一台專用電視——只顯示你要的畫面,用戶無法跳出。

常見 Kiosk 應用場景

Kiosk 模式常見場景:
🏪 POS 收銀系統 → 只顯示收銀介面
🏥 醫院叫號系統 → 只顯示叫號畫面
🍔 速食店點餐機 → 只顯示點餐頁面
🏨 飯店 Check-in → 只顯示自助入住
🚉 車站資訊看板 → 只顯示時刻表
📊 工廠看板系統 → 只顯示即時產量

Chromium Kiosk Mode 基本設定

安裝 Chromium

# 更新套件庫 // 確保取得最新版本
sudo apt update // 執行套件更新

# 安裝 Chromium 瀏覽器 // Kiosk 模式的核心
sudo apt install -y chromium-browser // 安裝 Chromium

# 安裝無頭顯示套件 // 虛擬螢幕支援
sudo apt install -y xdotool unclutter // 安裝輔助工具

# 確認安裝成功 // 檢查版本號
chromium-browser --version // 顯示 Chromium 版本

基本 Kiosk 啟動指令

# 啟動全螢幕 Kiosk 模式 // 最基本的 Kiosk 指令
chromium-browser \
  --kiosk \                    // 啟用 Kiosk 模式
  --noerrdialogs \             // 不顯示錯誤對話框
  --disable-infobars \         // 不顯示資訊列
  --no-first-run \             // 跳過首次執行設定
  --disable-translate \        // 停用翻譯提示
  --disable-features=TranslateUI \  // 停用翻譯 UI
  --check-for-update-interval=31536000 \  // 停用自動更新檢查
  --incognito \                // 無痕模式(不留紀錄)
  'http://localhost:5000'      // 指定要顯示的網頁

自動開機啟動 Kiosk

方法一:使用 autostart 設定

# 建立 autostart 目錄 // 存放自動啟動設定
mkdir -p /home/pi/.config/autostart // 建立目錄

# 建立 autostart 桌面檔案 // 自動啟動設定
cat > /home/pi/.config/autostart/kiosk.desktop << 'EOF'  // 寫入設定檔
[Desktop Entry]                // 桌面項目設定區塊
Type=Application               // 類型為應用程式
Name=Kiosk                     // 名稱為 Kiosk
Exec=/home/pi/kiosk.sh         // 執行啟動腳本
X-GNOME-Autostart-enabled=true // 啟用自動啟動
EOF

方法二:使用 systemd service

# 建立 systemd service 檔案 // 系統服務設定
sudo cat > /etc/systemd/system/kiosk.service << 'EOF'  // 寫入 service 檔
[Unit]                               // 單元設定區塊
Description=Chromium Kiosk Mode      // 服務描述
Wants=graphical.target               // 需要圖形介面
After=graphical.target               // 在圖形介面後啟動

[Service]                            // 服務設定區塊
Environment=DISPLAY=:0               // 設定顯示器環境變數
Environment=XAUTHORITY=/home/pi/.Xauthority  // 設定 X 授權
Type=simple                          // 服務類型為簡單
ExecStart=/home/pi/kiosk.sh          // 啟動腳本路徑
Restart=on-failure                   // 失敗時自動重啟
RestartSec=5                         // 重啟間隔 5 秒
User=pi                              // 以 pi 用戶執行

[Install]                            // 安裝設定區塊
WantedBy=graphical.target            // 隨圖形介面啟動
EOF

# 啟用並啟動服務 // 讓服務開機自動執行
sudo systemctl enable kiosk.service  // 啟用開機自動啟動
sudo systemctl start kiosk.service   // 立即啟動服務
sudo systemctl status kiosk.service  // 檢查服務狀態

防止用戶跳出(禁用快捷鍵)

禁用常見快捷鍵

# 建立禁用快捷鍵腳本 // 防止用戶跳出 Kiosk
cat > /home/pi/disable_shortcuts.sh << 'EOF'  // 寫入腳本
#!/bin/bash                          // 指定 Bash 直譯器

# 禁用 Alt+F4 // 防止關閉視窗
xdotool key --clearmodifiers alt+F4  // 清除 Alt+F4 綁定

# 禁用 Ctrl+Alt+Delete // 防止開啟工作管理員
xdg-settings set default-web-browser chromium-browser.desktop  // 固定瀏覽器

# 使用 xbindkeys 攔截快捷鍵 // 進階快捷鍵管理
cat > /home/pi/.xbindkeysrc << 'KEYS'  // 寫入快捷鍵設定
"echo '已禁用'"                    // 快捷鍵動作(無效化)
    Alt + F4                         // 攔截 Alt+F4

"echo '已禁用'"                    // 快捷鍵動作(無效化)
    Control + w                      // 攔截 Ctrl+W

"echo '已禁用'"                    // 快捷鍵動作(無效化)
    Alt + Tab                        // 攔截 Alt+Tab
KEYS

# 啟動 xbindkeys // 套用快捷鍵攔截
xbindkeys                           // 執行快捷鍵攔截
EOF

chmod +x /home/pi/disable_shortcuts.sh  // 設定腳本可執行

隱藏滑鼠游標

# 安裝 unclutter // 自動隱藏閒置游標
sudo apt install -y unclutter        // 安裝 unclutter

# 啟動時隱藏游標 // 5 秒無操作就隱藏
unclutter -idle 5 -root &           // 背景執行隱藏游標

觸控螢幕校準

安裝校準工具

# 安裝觸控校準工具 // 讓觸控點對準螢幕位置
sudo apt install -y xinput-calibrator  // 安裝 xinput-calibrator

# 執行校準程序 // 跟著螢幕點四個角落
xinput_calibrator                    // 啟動校準精靈

# 查看觸控裝置列表 // 找出觸控螢幕裝置 ID
xinput list                          // 列出所有輸入裝置

使用 C# 處理觸控事件

// 觸控螢幕事件處理服務 // 處理 Kiosk 的觸控輸入
public class TouchScreenService // 觸控螢幕服務類別
{
    private readonly ILogger<TouchScreenService> _logger; // 日誌記錄器

    // 建構函式注入日誌服務 // 依賴注入模式
    public TouchScreenService(ILogger<TouchScreenService> logger) // 注入 Logger
    {
        _logger = logger; // 儲存日誌記錄器
    }

    // 處理觸控座標 // 將觸控位置轉換為畫面座標
    public (int X, int Y) CalibrateTouch( // 校準觸控座標方法
        int rawX, int rawY, // 原始觸控座標
        int screenWidth, int screenHeight) // 螢幕解析度
    {
        // 校準比例計算 // 將原始座標映射到螢幕
        double scaleX = (double)screenWidth / 4096; // X 軸縮放比例
        double scaleY = (double)screenHeight / 4096; // Y 軸縮放比例

        int calibratedX = (int)(rawX * scaleX); // 計算校準後 X
        int calibratedY = (int)(rawY * scaleY); // 計算校準後 Y

        _logger.LogDebug("觸控校準:({RawX},{RawY}) → ({CalX},{CalY})", // 記錄校準結果
            rawX, rawY, calibratedX, calibratedY); // 傳入參數

        return (calibratedX, calibratedY); // 回傳校準後座標
    }
}

螢幕旋轉設定(直式/橫式)

旋轉螢幕

# 查看目前螢幕資訊 // 確認螢幕名稱
xrandr                               // 顯示螢幕資訊

# 旋轉螢幕 90 度(直式) // 適合點餐機、叫號機
xrandr --output HDMI-1 --rotate left  // 逆時針旋轉 90 度

# 旋轉螢幕 180 度(倒掛) // 適合天花板螢幕
xrandr --output HDMI-1 --rotate inverted  // 旋轉 180 度

# 恢復橫式 // 標準方向
xrandr --output HDMI-1 --rotate normal  // 恢復正常方向

# 永久設定旋轉 // 寫入啟動設定
echo 'xrandr --output HDMI-1 --rotate left' >> /home/pi/.bashrc  // 開機自動旋轉

旋轉觸控座標同步

# 旋轉觸控座標對應 // 螢幕旋轉後觸控也要跟著轉
TOUCH_ID=$(xinput list --id-only "touchscreen")  // 取得觸控裝置 ID

# 設定觸控旋轉矩陣(左轉 90 度) // 數學矩陣轉換
xinput set-prop $TOUCH_ID 'Coordinate Transformation Matrix' \
  0 -1 1 \    // 旋轉矩陣第一列
  1  0 0 \    // 旋轉矩陣第二列
  0  0 1      // 旋轉矩陣第三列

自動重新整理(避免記憶體洩漏)

JavaScript 自動重新整理

// Kiosk 頁面自動重新整理服務 // 防止長時間執行記憶體洩漏
public class KioskRefreshService // 自動重新整理服務類別
{
    // 產生自動重新整理的 JavaScript // 注入到 Kiosk 頁面
    public string GenerateAutoRefreshScript( // 產生 JS 腳本方法
        int intervalMinutes = 30) // 預設每 30 分鐘刷新
    {
        // 回傳 JavaScript 程式碼 // 定時重新整理頁面
        return $@"
            <script>
                // 設定自動重新整理計時器 // 避免記憶體洩漏
                setInterval(function() {{ // 每隔指定時間執行
                    // 檢查是否閒置 // 有人操作就不刷新
                    if (Date.now() - lastInteraction > {intervalMinutes * 60 * 1000}) {{ // 判斷閒置時間
                        location.reload(); // 重新整理頁面
                    }}
                }}, {intervalMinutes * 60 * 1000}); // 設定間隔毫秒數

                // 記錄最後互動時間 // 追蹤用戶操作
                var lastInteraction = Date.now(); // 初始化互動時間
                document.addEventListener('click', function() {{ // 監聽點擊事件
                    lastInteraction = Date.now(); // 更新互動時間
                }});
                document.addEventListener('touchstart', function() {{ // 監聽觸控事件
                    lastInteraction = Date.now(); // 更新互動時間
                }});
            </script>"; // 結束 JavaScript 區塊
    }
}

記憶體監控自動重啟

# 記憶體監控腳本 // 記憶體不足時自動重啟 Chromium
cat > /home/pi/monitor_memory.sh << 'EOF'  // 建立監控腳本
#!/bin/bash                          // 指定直譯器

while true; do                       // 無限迴圈監控
    # 取得可用記憶體(MB) // 計算剩餘記憶體
    FREE_MEM=$(free -m | awk '/^Mem:/{print $7}')  // 取得可用 MB

    # 如果可用記憶體低於 100MB // 觸發重啟條件
    if [ "$FREE_MEM" -lt 100 ]; then  // 判斷記憶體門檻
        echo "$(date): 記憶體不足 ${FREE_MEM}MB,重啟 Chromium"  // 記錄日誌
        pkill -f chromium              // 殺掉 Chromium 程序
        sleep 3                        // 等待 3 秒
        /home/pi/kiosk.sh &            // 重新啟動 Kiosk
    fi

    sleep 60                           // 每 60 秒檢查一次
done
EOF

chmod +x /home/pi/monitor_memory.sh  // 設定可執行權限

多螢幕設定(主螢幕+客顯)

雙螢幕配置

# 查看所有螢幕 // 確認有幾個輸出
xrandr --listmonitors                // 列出所有螢幕

# 設定雙螢幕(延伸模式) // 主螢幕右邊接客顯
xrandr --output HDMI-1 --auto --primary \  // 主螢幕設定
       --output HDMI-2 --auto --right-of HDMI-1  // 客顯在右邊

# 設定雙螢幕(鏡像模式) // 兩個螢幕顯示一樣
xrandr --output HDMI-1 --auto --primary \  // 主螢幕設定
       --output HDMI-2 --auto --same-as HDMI-1  // 客顯鏡像

C# 雙螢幕 Kiosk 管理

// 雙螢幕 Kiosk 管理器 // 管理主螢幕和客顯
public class DualScreenKiosk // 雙螢幕管理類別
{
    // 螢幕配置模型 // 記錄每個螢幕的設定
    public class ScreenConfig // 螢幕設定類別
    {
        public string OutputName { get; set; } = ""; // 螢幕輸出名稱(如 HDMI-1)
        public int Width { get; set; } // 螢幕寬度像素
        public int Height { get; set; } // 螢幕高度像素
        public string Role { get; set; } = "main"; // 角色:main 或 customer
        public string Url { get; set; } = ""; // 要顯示的網址
    }

    // 產生雙螢幕啟動腳本 // 自動開兩個 Chromium 視窗
    public string GenerateLaunchScript( // 產生啟動腳本方法
        ScreenConfig mainScreen, // 主螢幕設定
        ScreenConfig customerScreen) // 客顯設定
    {
        // 組合 bash 啟動腳本 // 分別在兩個螢幕開 Chromium
        return $@"#!/bin/bash
# 主螢幕 Kiosk // 操作員使用的畫面
chromium-browser --kiosk --window-position=0,0 \
  --window-size={mainScreen.Width},{mainScreen.Height} \
  '{mainScreen.Url}' &

# 客顯螢幕 // 給客人看的畫面
chromium-browser --kiosk --window-position={mainScreen.Width},0 \
  --window-size={customerScreen.Width},{customerScreen.Height} \
  '{customerScreen.Url}' &
"; // 結束腳本字串
    }
}

完整的 kiosk.sh 啟動腳本

#!/bin/bash                              // 指定 Bash 直譯器
# kiosk.sh - 完整的 Kiosk 啟動腳本 // 一鍵啟動所有 Kiosk 元件

# === 基本設定 === // 可依需求修改
KIOSK_URL="http://localhost:5000"      // Kiosk 要顯示的網址
SCREEN_ROTATION="normal"               // 螢幕旋轉:normal/left/right/inverted
REFRESH_INTERVAL=1800                    // 自動重新整理間隔(秒)
LOG_FILE="/home/pi/kiosk.log"          // 日誌檔案路徑

# === 記錄啟動時間 === // 方便除錯
echo "$(date): Kiosk 啟動中..." >> $LOG_FILE  // 寫入啟動日誌

# === 等待桌面環境就緒 === // 確保 X11 已啟動
sleep 5                                  // 等待 5 秒讓桌面就緒

# === 螢幕旋轉 === // 依設定旋轉螢幕
xrandr --output HDMI-1 --rotate $SCREEN_ROTATION  // 執行螢幕旋轉

# === 隱藏游標 === // 無操作 3 秒後隱藏
unclutter -idle 3 -root &               // 背景隱藏游標

# === 停用螢幕保護 === // 防止螢幕變黑
xset s off                               // 關閉螢幕保護
xset -dpms                              // 關閉電源管理
xset s noblank                           // 關閉螢幕空白

# === 禁用快捷鍵 === // 防止用戶跳出
xbindkeys                               // 啟動快捷鍵攔截

# === 清除 Chromium 快取 === // 避免快取問題
rm -rf /home/pi/.config/chromium/Default/Cache/*  // 清除快取檔案

# === 啟動 Chromium Kiosk === // 主要 Kiosk 程序
chromium-browser \
  --kiosk \                              // 全螢幕 Kiosk 模式
  --noerrdialogs \                       // 隱藏錯誤對話框
  --disable-infobars \                   // 隱藏資訊列
  --no-first-run \                       // 跳過首次執行
  --disable-translate \                  // 停用翻譯
  --disable-features=TranslateUI \       // 停用翻譯介面
  --disable-session-crashed-bubble \     // 停用當機氣泡
  --disable-component-update \           // 停用元件更新
  --check-for-update-interval=31536000 \ // 極長更新間隔
  --incognito \                          // 無痕模式
  --disk-cache-size=0 \                  // 不使用磁碟快取
  "$KIOSK_URL" &                       // 開啟目標網址

# === 記錄啟動完成 === // 確認 Kiosk 已啟動
echo "$(date): Kiosk 啟動完成" >> $LOG_FILE  // 寫入完成日誌

錯誤自動重啟腳本

#!/bin/bash                              // 指定直譯器
# watchdog.sh - 監控並自動重啟 // Kiosk 的看門狗

KIOSK_URL="http://localhost:5000"      // Kiosk 網址
CHECK_INTERVAL=30                        // 每 30 秒檢查一次
LOG_FILE="/home/pi/watchdog.log"       // 看門狗日誌

while true; do                           // 無限迴圈監控
    # 檢查 Chromium 是否在執行 // 確認程序存活
    if ! pgrep -x "chromium" > /dev/null; then  // 如果 Chromium 沒在跑
        echo "$(date): Chromium 已停止,重新啟動..." >> $LOG_FILE  // 記錄異常
        /home/pi/kiosk.sh &             // 重新啟動 Kiosk
    fi

    # 檢查網頁是否能連線 // 確認 Web Server 正常
    HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" $KIOSK_URL)  // 取得 HTTP 狀態碼
    if [ "$HTTP_CODE" != "200" ]; then  // 如果不是 200 OK
        echo "$(date): 網頁回應 $HTTP_CODE,等待恢復..." >> $LOG_FILE  // 記錄異常
    fi

    sleep $CHECK_INTERVAL                // 等待下次檢查
done

🤔 我這樣寫為什麼會錯?

❌ 錯誤:直接執行 chromium --kiosk 卻看到白畫面

# 錯誤寫法 // 沒等 Web Server 就啟動 Kiosk
chromium-browser --kiosk http://localhost:5000  // 直接啟動(Web Server 還沒準備好)

✅ 正確:先等 Web Server 就緒再啟動

# 正確寫法 // 確認 Web Server 已啟動
while ! curl -s http://localhost:5000 > /dev/null; do  // 迴圈等待 Server 就緒
    echo "等待 Web Server 啟動..."   // 顯示等待訊息
    sleep 2                            // 每 2 秒重試
done
chromium-browser --kiosk http://localhost:5000  // Server 就緒後再啟動 Kiosk

❌ 錯誤:螢幕旋轉後觸控位置偏移

# 錯誤寫法 // 只旋轉螢幕沒旋轉觸控
xrandr --output HDMI-1 --rotate left   // 旋轉螢幕
# 觸控座標還是原本的方向 ← 點哪裡都不對! // 忘記同步觸控矩陣

✅ 正確:螢幕和觸控一起旋轉

# 正確寫法 // 螢幕和觸控都要旋轉
xrandr --output HDMI-1 --rotate left   // 旋轉螢幕
xinput set-prop 'touchscreen' 'Coordinate Transformation Matrix' \  // 同步旋轉觸控
  0 -1 1 1 0 0 0 0 1                  // 左轉 90 度的矩陣

❌ 錯誤:Kiosk 記憶體越用越多

// 錯誤寫法 // 沒有自動重新整理機制
public class KioskPage // Kiosk 頁面類別
{
    // 頁面永遠不刷新 // 長時間運行記憶體會洩漏
    public void Render() // 渲染頁面方法
    {
        // 只渲染一次就不管了 // 記憶體只增不減
    }
}

✅ 正確:加入定時重新整理和記憶體監控

// 正確寫法 // 定期重新整理 + 監控記憶體
public class SmartKioskPage // 智慧 Kiosk 頁面類別
{
    private readonly Timer _refreshTimer; // 重新整理計時器

    public SmartKioskPage() // 建構函式
    {
        // 每 30 分鐘自動重新整理 // 避免記憶體洩漏
        _refreshTimer = new Timer(RefreshPage, null, // 建立計時器
            TimeSpan.FromMinutes(30), // 30 分鐘後第一次觸發
            TimeSpan.FromMinutes(30)); // 之後每 30 分鐘觸發
    }

    private void RefreshPage(object? state) // 重新整理回呼方法
    {
        // 檢查是否有用戶正在操作 // 避免打斷操作
        if (IsUserIdle()) // 如果用戶閒置
        {
            ForceRefresh(); // 執行頁面重新整理
        }
    }

    private bool IsUserIdle() => true; // 判斷用戶是否閒置
    private void ForceRefresh() { } // 強制重新整理
}

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊