最近一直在Linux系统下玩些偏操作系统low-level的东西,发现有些常用的工具冷门功能不是自带的,需要从源代码开始自己编译一个版本。本篇就是给大家演示下如何从源代码编译出鼎鼎大名的网络调试命令行工具——cURL

缘起

最近遇到一个测试场景:要在一个Nginx Docker容器内进行网络联通测试。常用的网络调试工具很多,如cURL、dig、nslookup等等。而在Nginx镜像里一般不会自带这些工具,当然,可以通过Dockerfile打造属于你的“瑞士军刀”版本的Nginx镜像。其实,Docker所在的Linux主机上一般都会自带这些工具了。那么有没有一种方法,可以直接利用Linux主机上的这些命令行工具,在容器内执行相关命令呢?

答案是,。那就是:ip netns exec(今天不是讲这个命令的背景的,感兴趣的童鞋可以自行Google)。有了这个命令我们可以这样在容器内执行cURL命令:

# 准备工作
nskey=$(docker inspect httptest -f "{{.NetworkSettings.SandboxKey}}")
mkdir -p /var/run/netns
ln -s $nskey /var/run/netns/dockercontainer
# 正式开始
ip netns exec dockercontainer ip a # 能看的到就是容器内的网络设备
ip netns exec dockercontainer curl www.baidu.com

问题来了

当你执行上面示例命令的最后一行,会发现执行失败:

> ip netns exec dockercontainer curl www.baidu.com
curl: (6) Could not resolve host: www.baidu.com

检查下这个ns里dns配置:

> ip netns exec httpserver cat /etc/resolv.conf
# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients to the
# internal DNS stub resolver of systemd-resolved. This file lists all
# configured search domains.
#
# Run "systemd-resolve --status" to see details about the uplink DNS servers
# currently in use.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.

nameserver 127.0.0.53
options edns0

原来这个ns里的nameserver是用了本机的回环地址,由于在容器内,所以就无法进行域名解析了。认真阅读上文的信息,你会关注到systemd-resolved 这个东西,感兴趣的大家可以自行Google,这里,我尝试的是如下这个命令:

# 使用了--dns-servers这个参数,在执行命令时为curl指定name server
> ip netns exec dockercontainer curl --dns-servers 8.8.8.8 www.baidu.com
curl: (4) A requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision.

执行报错了,错误信息显示–dns-servers 这个参数所需的lib模块没有在当前cURL编译时添加进去,果然没有这么简单。。。

DIY解决方案

既然默认的cURL没有自带这个命令,那么我们就造一个出来,发扬Geek精神。

我尝试了一遍,其实也没有那么复杂。大家可以follow下面的gist试试看。注意,在执行./configure 命令时,一定要把其他你需要的模块都添加上,不然就是捡了西瓜,丢了芝麻。

重新执行下如下命令,成功返回:

> ip netns exec dockercontainer curl-new --dns-servers 8.8.8.8  www.baidu.com

<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> 
...此处略去若干行
<img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>

1 对 “打造你自己的cURL命令”的想法;

  1. 作者,你好!我是腾讯云+社区的小编,关注了您分享的技术文章,觉得很棒,我们诚挚邀请您加入云+社区,与我们众多的社区作者一起为开发者分享技术干货。这个是我们云+社区【腾讯云自媒体分享计划】入驻流程和权益介绍的地址:https://cloud.tencent.com/developer/support-plan。如果您愿意加入或者想了解更多的信息请联系我~微信:suimgi-7,我们对您的加入充满期待。

发表评论

邮箱地址不会被公开。 必填项已用*标注