找回密碼
 立即註冊
惟家LINE群QRCODE
    查看: 0|回覆: 0

    shell_command 與 command_line:讓 HA 去執行系統指令

    [複製鏈接]

    !lvup!   100%

    363

    主題

    27

    回帖

    2200萬

    積分

    管理員

    積分
    22005752
    發表於 3 天前 | 顯示全部樓層 |閱讀模式
    有些事 HA 的整合做不到,但一行指令就解決。
    這篇講怎麼把指令接進 HA。

    先講清楚兩者的差別


    • shell_command — 執行動作,不在乎輸出(像按一個鈕)
    • command_line — 執行並讀取輸出,做成感測器或開關




    shell_command:最簡單的形式
    1. shell_command:
    2.   喚醒電腦: "wakeonlan AA:BB:CC:DD:EE:FF"
    3.   重啟路由器: "ssh -i /config/id_rsa root@192.168.1.1 reboot"
    4.   備份設定: "tar czf /media/backup/config-$(date +%F).tar.gz /config"
    複製代碼

    在自動化裡呼叫:
    1. actions:
    2.   - action: shell_command.喚醒電腦
    複製代碼

    帶參數
    1. shell_command:
    2.   推播到手機: >
    3.     curl -s -X POST -d "token=xxx&message={{ msg }}" https://example.com/api
    複製代碼

    呼叫:
    1.   - action: shell_command.推播到手機
    2.     data:
    3.       msg: 洗衣機好了
    複製代碼

    重要:參數一定要處理引號

    使用者輸入的內容直接塞進 shell 指令是命令注入的典型場景。
    訊息裡有個分號或反引號就可能執行到別的東西。

    HA 有幫你做基本跳脫,但不要依賴它
    安全的做法是把參數放進環境變數,或者乾脆改用 python_script。

    command_line:做成感測器
    1. command_line:
    2.   - sensor:
    3.       name: 主機溫度
    4.       unique_id: host_cpu_temp
    5.       command: "cat /sys/class/thermal/thermal_zone0/temp"
    6.       unit_of_measurement: "°C"
    7.       value_template: "{{ (value | float(0) / 1000) | round(1) }}"
    8.       scan_interval: 60
    9.       device_class: temperature
    10.       state_class: measurement
    11.   - sensor:
    12.       name: 外網 IP
    13.       unique_id: wan_ip
    14.       command: "curl -s https://api.ipify.org"
    15.       scan_interval: 1800
    16.   - sensor:
    17.       name: NAS 磁碟使用率
    18.       unique_id: nas_disk_usage
    19.       command: >
    20.         ssh -i /config/ssh/id_rsa -o StrictHostKeyChecking=no
    21.         admin@192.168.1.20 "df -h /volume1 | tail -1 | awk '{print \$5}' | tr -d '%'"
    22.       unit_of_measurement: "%"
    23.       scan_interval: 600
    複製代碼



    command_line 也能做開關
    1. command_line:
    2.   - switch:
    3.       name: 電腦電源
    4.       unique_id: pc_power
    5.       command_on: "wakeonlan AA:BB:CC:DD:EE:FF"
    6.       command_off: >
    7.         ssh -i /config/ssh/id_rsa user@192.168.1.30 "shutdown /s /t 0"
    8.       command_state: "ping -c1 -W1 192.168.1.30 > /dev/null && echo on || echo off"
    9.       value_template: "{{ value == 'on' }}"
    10.       scan_interval: 30
    複製代碼

    三個一定會遇到的坑

    坑一:HAOS 裡面沒有你以為有的指令

    HA 的容器很精簡。沒有 ssh、沒有 wakeonlan、沒有 jq
    連 curl 都是簡化版。

    確認方式:設定 → 附加元件 → Terminal & SSH → 進去打那個指令

    但注意 —— Terminal 附加元件跟 HA Core 是不同的容器
    在 Terminal 裡能跑,不代表 shell_command 能跑。

    真正的測試方法:寫一個 command_line sensor 執行 which 指令名
    看回傳什麼。

    坑二:權限與工作目錄

    shell_command 以 HA 的使用者身分執行,工作目錄不保證是 /config。
    路徑一律寫絕對路徑。

    要用 ssh 的話,金鑰要放在 /config 底下(這樣才會被備份),
    而且權限要 600:
    1. chmod 600 /config/ssh/id_rsa
    複製代碼

    權限太開的話 ssh 會直接拒絕使用,而且錯誤訊息只在日誌裡。

    坑三:沒有輸出就看不到錯

    shell_command 失敗時,HA 只會在日誌寫一行 return code。

    除錯做法:把指令改成把輸出導到檔案
    1. shell_command:
    2.   測試: "你的指令 > /config/cmd.log 2>&1"
    複製代碼

    然後去看 /config/cmd.log。這招幾乎每次都能找出問題。

    更好的替代方案

    如果你只是要呼叫一個 HTTP API,不要用 shell_command + curl,
    用內建的 rest_command
    1. rest_command:
    2.   重啟印表機:
    3.     url: "http://192.168.1.40/api/restart"
    4.     method: POST
    5.     headers:
    6.       Authorization: "Bearer {{ states('input_text.printer_token') }}"
    7.     content_type: "application/json"
    8.     payload: '{"delay": 5}'
    複製代碼

    好處:不依賴容器裡有沒有 curl、錯誤訊息清楚、支援範本。

    同理,要讀 HTTP 回傳的資料做感測器,用 rest 平台,不要用 command_line + curl。

    安全底線


    • 指令裡不要寫死密碼,用 secrets.yaml
    • ssh 金鑰用專用的、限制指令的(authorized_keys 可以加 command= 限定)
    • 接受外部輸入的指令,一律先想有沒有注入風險


    ---

    我自己用 shell_command 的地方只剩兩個:WOL 喚醒電腦、
    和一個 rsync 備份。其他的能用內建整合就用內建,
    因為 shell_command 是最不容易除錯的那一種
    您需要登入後纔可以回帖 登入 | 立即註冊

    本版積分規則

    Archiver|手機版|惟家的智能論壇

    GMT+8, 2026-9-24 10:31 , Processed in 0.075953 second(s), 25 queries .

    快速回覆 返回頂部 返回列表