滥用cURL与Redis沟通

时间:2015-10-20 17:31:45

标签: linux http curl tcp redis

我想向Redis发送PING以检查连接是否正常,现在我可以安装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 "",但我无法找到其他任何内容。知道我该怎么做吗?

7 个答案:

答案 0 :(得分:36)

当你想使用curl时,你需要REST over RESP,比如webdis,tinywebdis或turbowebdis。见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

我已经构建了一个强大的bash函数,它可以不惜任何代价ping redis实例

    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

答案 1 :(得分:30)

不卷曲,但不需要HTTP接口或nc(非常适用于没有安装nc的容器)

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

应该给你

+PONG

您可以从this fantastic article了解更多有关正在发生的事情。

答案 2 :(得分:14)

我需要为@Markus提供的nc添加一个睡眠,让它从远程系统工作:

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

有关详细信息,请参阅Request/Response protocols and RTT: Redis Pipelining

答案 3 :(得分:2)

我在Mac(Catalina)上运行了docker。 我使用

运行了一个redis容器
docker run --name redis-mac -p 6379:6379 -d redis

然后我使用计算机的IP测试了连接

echo PING | nc 192.168.1.100 6379

已收到

+PONG

无法使用docker inspect redis-mac中的IP。

实际上,我正在测试具有Redis作为缓存提供程序的Spring引导应用程序。所以我需要测试连接。 如果您是docker的新手,这里是第一个命令的一些解释: 使用主机端口6379和docker端口6379将redis作为容器运行,并将容器命名为redis-mac。现在,如果该镜像已可用,则docker守护程序将创建一个容器,否则它将从docker hub提取该镜像,然后运行该容器。 您可以执行docker ps检查容器是否正在运行。

答案 4 :(得分:1)

详细说明@Joel B的好答案。我需要在Docker容器的shell脚本中使用它,没有卷曲,没有redis-cli和nc ... 我正在测试的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

答案 5 :(得分:0)

您也可以使用telnet localhost 6379,如果连接成功,则键入ping

要出去使用quit

答案 6 :(得分:0)

如果Redis实例需要通过验证,这可能会有所帮助:

$ exec 3<>/dev/tcp/127.0.0.1/6379 && echo -e "AUTH {requirepass-string-from-redis-config} \r\n PING\r\n" >&3 && head -c 12 <&3
+OK
+PONG

用来自'requirepass'redis.conf的字符串替换{requirepass-string-from-redis-config}