web-dev-qa-db-ja.com

cURLを悪用してRedisと通信する

接続が機能しているかどうかを確認するためにPINGをRedisに送信したいので、今すぐredis-cliをインストールできますが、curlはすでに存在します。それで、どうすればcurlを悪用してそれを行うことができますか?基本的に、ここで送信するものをオフにする必要があります。

> GET / HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: localhost:6379
> Accept: */*
> 
-ERR wrong number of arguments for 'get' command
-ERR unknown command 'User-Agent:'
-ERR unknown command 'Host:'
-ERR unknown command 'Accept:'

User-Agentを追加することで-A ""を完全に削除することができましたが、他に何も見つかりません。どうすればそれができますか?

22
Mahoni

Curlを使用する場合は、REST webdis、tinywebdis、turbowebdisなどのRESPを使用する必要があります。 https://github.com/markuman/tinywebdis#turbowebdis-tinywebdis-を参照してください。 -cherrywebdis

$ curl -w '\n' http://127.0.0.1:8888/ping
{"ping":"PONG"}

RedisのRESTインターフェースがなければ、netcatを使用できます。

$ (printf "PING\r\n";) | nc localhost 6379 
+PONG

Netcatでは、自分でRESPプロトコルを構築する必要があります。 http://redis.io/topics/protocol を参照してください

更新2018-01-09

私は、tcpを超えるコストでredisインスタンスをpingする強力なbash関数を構築しました

    function redis-ping() {
            # ping a redis server at any cost
            redis-cli -h $1 ping 2>/dev/null || \
                    echo $((printf "PING\r\n";) | nc $1 6379 2>/dev/null || \
                    exec 3<>/dev/tcp/$1/6379 && echo -e "PING\r\n" >&3 && head -c 7 <&3)
    }

使用法 redis-ping localhost

41
Markus

カールしませんが、HTTPインターフェースまたはncは必要ありません(ncがインストールされていないコンテナーのようなものに最適)

exec 3<>/dev/tcp/127.0.0.1/6379 && echo -e "PING\r\n" >&3 && head -c 7 <&3

あなたに与えるべき

+PONG

何が起こっているかについて詳しくは この素晴らしい記事 をご覧ください。

33
Joel B

リモートシステムから動作させるには、@ Markusが提供するncにスリープを追加する必要がありました。

(printf "PING\r\n"; sleep 1) | nc remote.redis.hostname 6379

詳細については、 リクエスト/レスポンスプロトコルおよびRTT:Redis Pipelining を参照してください。

15
Peter M

@Joel Bの素晴らしい答えについて詳しく説明します。これは、カール、redis-cli、ncのないdockerコンテナのシェルスクリプトで必要でした。テストしているREDISは、ここからのkubernetesの公開redis-ha Helmチャートです。 https: //github.com/helm/charts/tree/master/stable/redis-ha

設定する変数は次のとおりです。

  • REDIS_Host = Redisマスターとセンチネルを含むホスト名(DNSアドレスまたはIP)(分離している場合はこれを別のホストに分割し、必要に応じてポートを変更します-ヘルムチャートではマスター/スレーブとセンチネルがあります)同じポッドで標準ポートを使用)

  • REDIS_STARTUP_TIMEOUT =あきらめるまで待機する最大秒数-デフォルトは10分

  • REDIS_STARTUP_RETRY =テスト間で待機する秒数-デフォルトは15秒

  • DEBUG =これをtrueに設定して、失敗した応答をエコーし​​ます

テクニックの複雑さはコメントに記載されています(山括弧を解読しようとするとき、特定の狂気から同僚と将来の自己を救うためにコメントを保持することをお勧めします)

# wait for 10 mins and check again every 15 seconds
let n=${REDIS_STARTUP_TIMEOUT:-600}
let m=${REDIS_STARTUP_RETRY:-15}
ready=false
while ((n > 0)); do
    # These scripts are the best way to check if redis is running without having access to nc, curl or redis-cli
    # They write a "PING" to the redis and sentinel ports on the hostname "dc-ecm-redis-ha"
    # and look for a "PONG+" in return.
    #
    # Detailed explanation:
    # -  3<>/dev/tcp... opens a file handle identified as #3 for input and output on the tcp Host and port
    #    The Host $REDIS_Host is defined in DNS by the Kubernetes _service_, and the port is for redis or sentinel
    #    (Uses linux's low-level network-as-filesystem support. Think of it as a sort of poor-man's telnet)
    # -  "PING" followed by carriage-return is sent to the port by redirecting to the handle with >&3
    # -  The response from the port is sent to the head command with <&3
    # -  The first 5 bytes of the response are captured with -c 5. This removes the linebreak (\r) from the response
    # -  Standard Shell $() around the whole thing stores the result in a variable (master or sentinel)
    # -  When Redis is NOT ready, the result is generally a failure in the exec or some other error, which goes
    #    to stderr, so we wrap it in  { } > 2>&1 to capture that error in the variable too.
    # -  Success is measured by "+PONG" being in the variable
    # -  If you set the variable DEBUG to "true" (or "TRUE" -> the {,,} lower-cases it) the failed responses are echoed
    # -  (There are easier ways to do this if you have redis-cli installed or nc, but typically you don't on a docker container)
    # -  The whole thing waits n seconds for Redis to be ready, checking every m seconds
    #
    master=$( { exec 3<>/dev/tcp/${REDIS_Host}/6379 && echo -e "PING\r\n" >&3 && head -c 5 <&3; } 2>&1 )
    sentinel=$( { exec 3<>/dev/tcp/${REDIS_Host}/26379 && echo -e "PING\r\n" >&3 && head -c 5 <&3; } 2>&1 )
    if [ "$sentinel" = "+PONG" -a "$master" = "+PONG" ]; then ready=true;
       break;
   else echo "$(date) : Waiting $n more seconds for Redis master and sentinel to respond to PING"
        [[ "${DEBUG,,}" = "true" ]] && echo "master response was [$master]";
        [[ "${DEBUG,,}" = "true" ]] && echo "sentinel response was [$sentinel]";
        sleep $m
        ((n-=m))
    fi
done

if [ "$ready" = true ]
    then echo "$(date) : REDIS is ready"
    # do something when Redis is ready
else
    echo "$(date) : ERROR: REDIS is still not ready. Giving up waiting"
    # do something when Redis fails
fi
1
Rhubarb