Uygulamalı Eğitimler

curl ile MQTT: Komut Satırından Publish ve Subscribe

curl'ü MQTT istemcisi olarak kullanın: -d ile publish edin, mqtt:// URL'leriyle subscribe olun, wildcard'ları kodlayın, ikili çıktıyı okuyun ve ne zaman mosquitto_pub'a geçeceğinizi bilin.

Güncellendi · 7 dk okuma

curl ile MQTT: Komut Satırından Publish ve Subscribe

Evet, curl MQTT konuşur. 7.70.0 sürümünden beri curl mqtt:// URL'lerini anlar: Bir GET (varsayılan) URL yolundaki topic'e subscribe olur, -d ile veri göndermek ise o topic'e publish eder. curl zaten sunucunuzda, CI runner'ınızda veya container'ınızda varsa, başka hiçbir şey kurmadan bir broker'ın bağlantı kabul edip etmediğini ve mesaj yönlendirip yönlendirmediğini kontrol edebilirsiniz.

İhtiyacınız olan iki komut
# Subscribe (Ctrl+C'ye basana kadar bekler)
curl mqtt://broker.connectmq.com/testmqtt/curl/demo

# Publish (ikinci bir terminalde)
curl -d "hello from curl" mqtt://broker.connectmq.com/testmqtt/curl/demo

Bu rehber; bu komutların nasıl davrandığını, çıktının tam formatını, önemli kısıtlamaları ve ne zaman gerçek bir MQTT istemcisine geçmeniz gerektiğini anlatıyor.

curl'ünüzde MQTT olup olmadığını kontrol edin

MQTT, derleme sırasında belirlenen bir özelliktir. Protokol listesinde mqtt arayın:

MQTT derlenmiş mi?
curl -V | grep -i protocols
# Protocols: dict file ftp ftps gopher ... mqtt pop3 pop3s rtsp ...

mqtt yoksa curl, bir mqtt:// URL'sine curl: (1) Protocol "mqtt" not supported ile yanıt verir (eski build'ler "or disabled in libcurl" ekler). Güncel macOS sürümleri, çoğu Linux dağıtımı ve resmi curlimages/curl Docker imajı bu desteği içerir; minimal bir build içermeyebilir.

Yerelde MQTT destekli curl yok mu? Resmi imajı kullanın
docker run --rm curlimages/curl -d "hi" mqtt://broker.connectmq.com/testmqtt/curl/demo

curl, MQTT'yi URL'lere nasıl eşler

curl işlemiMQTT davranışı
curl mqtt://host/a/bCONNECT, a/b için SUBSCRIBE, kesilene kadar her mesajı yazdırır
curl -d data mqtt://host/a/bCONNECT, data'yı a/b'ye PUBLISH (QoS 0), DISCONNECT
mqtt://host:1884/...Standart dışı port (varsayılan 1883)
-u user:passCONNECT paketinde kullanıcı adı ve parola
--max-time 10Bir subscription'ı 10 saniye sonra durdurur

Topic, baştaki eğik çizgi olmadan URL yoludur; yani mqtt://broker.connectmq.com/testmqtt/curl/demo, testmqtt/curl/demo topic'i anlamına gelir. curl, curl ile başlayan rastgele bir client ID üretir (örneğin curlMsFB2wMW, -v ile görünür) ve MQTT 3.1.1 kullanır.

Mesaj publish etmek

-d bir string alır ya da payload'ı dosyadan okumak için @dosya alır:

Publish varyasyonları
# Düz metin
curl -d "21.5" mqtt://broker.connectmq.com/testmqtt/curl/sensor/temp

# Shell'den JSON
curl -d '{"temp":21.5,"unit":"C"}' mqtt://broker.connectmq.com/testmqtt/curl/sensor/json

# Dosyadan payload, baytlar olduğu gibi korunur
curl --data-binary @reading.json mqtt://broker.connectmq.com/testmqtt/curl/sensor/json

# Kimlik bilgileriyle (broker'ınızın kullanıcı adı ve parolası)
curl -u "$MQTT_USER:$MQTT_PASS" -d "on" mqtt://broker.connectmq.com/testmqtt/curl/relay/1

Başarılı bir publish hiçbir şey yazdırmaz ve 0 durum koduyla çıkar; bu da curl'ü betiklerde ve health check'lerde kullanışlı kılar. Yalnız şunu unutmayın: 0 çıkış kodu sadece broker'ın bağlantıyı kabul ettiği ve curl'ün PUBLISH'i gönderdiği anlamına gelir. QoS 0'da onay yoktur; yani bu, birinin mesajı aldığını kanıtlamaz.

Subscribe olmak ve çıktıyı okumak

Bir subscription, siz Ctrl+C'ye basana veya bir zaman sınırı onu durdurana kadar sürer:

30 saniye boyunca subscribe olun
curl -N --max-time 30 mqtt://broker.connectmq.com/testmqtt/curl/sensor/temp

-N (--no-buffer), çıktıyı başka bir programa yönlendirdiğinizde curl'ün çıktıyı tamponlamak yerine her mesajı hemen yazmasını sağlar. Zaman sınırına ulaşıldığında curl 28 (operation timed out) koduyla çıkar. Bu, zaman sınırlı bir subscription'ın normal bitiş şeklidir, hata değildir.

Wildcard'lar URL kodlamalı olmalı

+ olduğu gibi yazılabilir, ancak # bir URL fragment'ı başlatır ve curl daha bir şey göndermeden kesilir. Onu %23 olarak kodlayın:

Çok seviyeli wildcard subscription
curl -N 'mqtt://broker.connectmq.com/testmqtt/curl/%23'          # testmqtt/curl/#
curl -N 'mqtt://broker.connectmq.com/testmqtt/curl/+/temp'       # tek seviye

Bir filtrenin neyle eşleştiğinden emin değil misiniz? Topic matcher ile deneyin veya MQTT topic'leri ve wildcard'lar yazısını okuyun.

Çıktı formatı

curl mesajları metin satırları olarak yazdırmaz. Aldığı her PUBLISH için şunları yazar:

  1. iki bayt: topic uzunluğu (big-endian),
  2. topic adı,
  3. payload; ayırıcı veya sonda satır sonu olmadan.

Wildcard subscription'da alınan bir mesajın gerçek bir kaydı:

curl subscribe çıktısının xxd görünümü
00000000: 0011 7465 7374 6d71 7474 2f63 7572 6c2f  ..testmqtt/curl/
00000010: 612f 627b 2274 223a 3231 2e35 7d         a/b{"t":21.5}

0x0011 17 eder; bu, testmqtt/curl/a/b topic'inin uzunluğudur ve JSON payload hemen ardından gelir. "Bir şey geldi mi?" sorusu için yeterlidir, ancak birden fazla mesaj birlikte geldiğinde ayrıştırmak zahmetlidir. Biraz Python akışı ayırabilir:

curl-mqtt-split.py — kullanım: curl -sN mqtt://... | python3 curl-mqtt-split.py
import sys

# curl akışını topic/payload çiftlerine ayırır.
# Payload'lar küçükse ve her okumada bir tane geliyorsa çalışır; curl payload uzunluğunu yazmaz.
buf = sys.stdin.buffer
while True:
    head = buf.read(2)
    if len(head) < 2:
        break
    n = int.from_bytes(head, "big")
    topic = buf.read(n).decode()
    payload = buf.read1(65536)   # bu mesajla birlikte gelen veri
    print(f"{topic}  {payload.decode(errors='replace')}", flush=True)

curl payload uzunluğunu yazmadığı için hiçbir ayrıştırıcı tamamen güvenilir olamaz. Mesajları programatik olarak işlemeniz gerekiyorsa, mosquitto_sub -v veya bir kütüphane kullanmak için tek başına bu bile yeterli bir sebeptir.

Bilmeniz gereken kısıtlamalar

Özellikcurlmosquitto_pub / mosquitto_sub
MQTT sürümü3.1.13.1, 3.1.1, 5
Publish QoSYalnızca 00, 1, 2
Retained publishHayır-r
TLS (mqtts, port 8883)Hayır--cafile, -p 8883
WebSocketsHayır (curl'deki ws:// düz bir WebSocket'tir, MQTT değil)Hayır (bir tarayıcı istemcisi kullanın)
Özel client ID, keep-alive, Last WillHayırEvet
Okunabilir subscribe çıktısıİkili çerçeveleme-v, topic payload satırları yazdırır

En önemli eksik TLS'tir. curl kılavuzu bunu açıkça söyler: "MQTT over TLS is not supported (yet)." Güvenilmeyen bir ağda production kimlik bilgilerini -u ile şifresiz 1883 portu üzerinden asla göndermeyin: Açık metin olarak iletilirler. Şifresiz bir TCP listener'a karşı yapılan bir smoke test'in ötesindeki her şey için mosquitto_pub ve mosquitto_sub ya da MQTT CLI kullanın; ikisi de TLS'i, MQTT 5'i ve tüm QoS seviyelerini destekler.

Hatalar ve çıkış kodları

GördüğünüzAnlamıÇözüm
curl: (1) Protocol "mqtt" not supportedBuild'inizde MQTT yokBaşka bir build veya curlimages/curl imajını kullanın
curl: (7) Failed to connect to ... port 1883Dinleyen bir şey yok ya da bir firewall engelliyorHost'u, portu ve firewall kurallarını kontrol edin
curl: (8) Weird server replyBroker CONNECT'i reddetti-v ile çalıştırıp CONNACK'i okuyun
Expected 0000 but got 0005 (-v ile)CONNACK dönüş kodu 5: yetkisiz-u user:pass ekleyin veya düzeltin, ACL'leri kontrol edin
curl: (28) Operation timed out--max-time dolduZaman sınırlı subscription'larda beklenen durum

-v ile, Expected 0000 but got 00XX mesajındaki son iki hane MQTT 3.1.1 CONNACK dönüş kodudur: 01 kabul edilemeyen protokol sürümü, 02 reddedilen tanımlayıcı, 03 sunucu kullanılamıyor, 04 hatalı kullanıcı adı veya parola, 05 yetkisiz. MQTT reason code aracı her birini açıklar; CONNACK reason code'ları yazısı da nedenleri ayrıntılı ele alır.

Betikler ve CI için curl smoke test'i

curl'ün güçlü yanları, her yerde bulunması ve temiz çıkış kodları döndürmesidir. Bu betik arka planda subscribe olur, benzersiz bir token publish eder ve geri gelip gelmediğini kontrol eder:

curl-mqtt-smoke.sh
#!/usr/bin/env bash
set -u
HOST="${MQTT_HOST:-broker.connectmq.com}"
TOPIC="testmqtt/curl-smoke/$(date +%s)-$$"
TOKEN="ping-$RANDOM"
OUT="$(mktemp)"

curl -sN --max-time 5 "mqtt://$HOST/$TOPIC" > "$OUT" &
SUB=$!
sleep 1                                   # SUBSCRIBE'ın ulaşması için zaman tanı

if ! curl -s -d "$TOKEN" "mqtt://$HOST/$TOPIC"; then
  echo "HATA: publish reddedildi (exit $?)"; exit 1
fi

wait "$SUB"                               # --max-time dolunca 28 ile çıkar
if grep -q "$TOKEN" "$OUT"; then
  echo "OK: mesaj $HOST üzerinden yönlendirildi"
else
  echo "HATA: mesaj alınmadı"; exit 1
fi
rm -f "$OUT"

Betiği broker erişimine ihtiyaç duyan makineden veya pipeline'dan çalıştırın: Başarılı olması DNS'i, TCP yolunu, CONNECT'i ve yönlendirmeyi tek seferde kanıtlar. TLS ve QoS kontrolleri içeren daha kapsamlı bir sürüm için MQTT smoke test betiği ve Bash betiklerinde MQTT yazılarına bakın.

curl komutlarınızın ürettiği mesajları görmek için online MQTT istemcisini açın ve aynı topic'e subscribe olun. Mesajların tarayıcıya ulaştığını görmek, iki yönü de aynı anda doğrular.

curl mesajlarını online istemcide izleyin

curl, hiçbir şey kurmadan "bu makine broker'a ulaşıp publish edebiliyor mu?" sorusunu yanıtlamanın en hızlı yoludur. MQTT desteği bilinçli olarak basittir: QoS 0, retain yok, TLS yok ve ikili çerçeveli çıktı. Onu smoke test'ler ve hızlı kontroller için kullanın; güvenliğe, güvenilirliğe veya okunabilir çıktıya ihtiyaç duyduğunuzda mosquitto_pub, MQTT CLI ya da bir istemci kütüphanesine geçin.

Sıkça sorulan sorular

curl, TLS üzerinden MQTT'yi (mqtts://) destekliyor mu?

Çoğu sistemle gelen curl sürümlerinde hayır: curl kılavuzu TLS üzerinden MQTT'nin desteklenmediğini belirtir. curl'ü yalnızca şifresiz 1883 TCP portuna karşı hızlı kontroller için kullanın; 8883 portunda TLS için mosquitto_pub, MQTT CLI veya bir kütüphane kullanın.

curl retained veya QoS 1 mesaj publish edebilir mi?

Hayır. curl, QoS 0 ile ve retain bayrağı kapalı olarak publish eder; bunları değiştirecek bir seçenek yoktur. Retained mesajlara, QoS 1/2'ye veya MQTT 5 özelliklerine ihtiyacınız varsa mosquitto_pub'ı ya da online istemciyi kullanın.

curl neden her MQTT mesajından önce garip karakterler gösteriyor?

Subscribe olurken curl, aldığı her PUBLISH'i 2 baytlık topic uzunluğu, topic adı ve ardından payload olarak, araya ayırıcı koymadan yazar. İlk iki bayt ikili olduğundan terminalde anlamsız karakterler olarak görünür. Çıktıyı okumak için xxd'den veya küçük bir ayrıştırıcıdan geçirin.