41 | Linux/Mac实验环境搭建与URI查询参数

你好,我是Chrono。

先要说一声“抱歉”。由于工作比较紧张、项目实施频繁出差,导致原本预定的“答疑篇”迟迟没有进展,这次趁着“十一”长假,总算赶出了两期,集中回答几个同学们问得比较多的问题:Linux/Mac实验环境搭建(第7讲),URI查询参数(第11讲),还有DHE/ECDHE算法的原理(第26讲),后续有时间可能还会再陆续补充完善。

很高兴在时隔一个多月后与你再次见面,废话不多说了,让我们开始吧。

Linux上搭建实验环境

我们先来看一下如何在Linux上搭建课程的实验环境。

首先,需要安装OpenResty,但它在Linux上提供的不是zip压缩包,而是各种Linux发行版的预编译包,支持常见的Ubuntu、Debian、CentOS等等,而且官网上有非常详细安装步骤。

以Ubuntu为例,只要“按部就班”地执行下面的几条命令就可以了,非常轻松:

# 安装导入GPG公钥所需的依赖包:
sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates


# 导入GPG密钥:
wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -


# 安装add-apt-repository命令
sudo apt-get -y install --no-install-recommends software-properties-common


# 添加官方仓库:
sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"


# 更新APT索引:
sudo apt-get update


# 安装 OpenResty
sudo apt-get -y install openresty

全部完成后,OpenResty会安装到“/usr/local/openresty”目录里,可以用它自带的命令行工具“resty”来验证是否安装成功:

$resty -v
resty 0.23
nginx version: openresty/1.15.8.2
built with OpenSSL 1.1.0k  28 May 2019

有了OpenResty,就可以从GitHub上获取http_study项目的源码了,用“git clone”是最简单快捷的方法:

git clone https://github.com/chronolaw/http_study

在Git仓库的“www”目录,我为Linux环境补充了一个Shell脚本“run.sh”,作用和Windows下的start.bat、stop.bat差不多,可以简单地启停实验环境,后面可以接命令行参数start/stop/reload/list:

cd http_study/www/    #脚本必须在www目录下运行,才能找到nginx.conf
./run.sh start        #启动实验环境
./run.sh list         #列出实验环境的Nginx进程
./run.sh reload       #重启实验环境
./run.sh stop         #停止实验环境

启动OpenResty之后,就可以用浏览器或者curl来验证课程里的各个测试URI,但之前不要忘记修改“/etc/hosts”添加域名解析,例如:

curl -v "http://127.0.0.1/"
curl -v "http://www.chrono.com/09-1"
curl -k "https://www.chrono.com/24-1?key=1234"
curl -v "http://www.chrono.com/41-1"

Mac上搭建实验环境

看完了Linux,我们再来看一下Mac。

这里我用的是两个环境:Mac mini 和 MacBook Air,不过都是好几年前的“老古董”了,系统是10.13 High Sierra和10.14 Mojave(更早的版本没有测试,但应该也都可以)。

首先要保证Mac里有第三方包管理工具homebrew,可以用下面的命令安装:

#先安装Mac的homebrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

然后,要用homebrew安装OpenResty,但它在Mac上的安装过程和Linux不同,不是预编译包,而是要下载许多相关的源码(如OpenSSL),然后再用clang本地编译,大概要花上五六分钟的时间,整体上比较慢,要有点耐心。

#使用homebrew安装OpenResty
brew install openresty/brew/openresty

安装完OpenResty,后续的操作就和Linux一样了,“git clone”项目源码:

git clone https://github.com/chronolaw/http_study

然后,进“http_study/www”目录,用脚本“run.sh”启停实验环境,用Safari或者curl测试。

Linux/Mac下的抓包

Linux和Mac里都有图形界面版本的Wireshark,抓包的用法与Windows完全一样,简单易用。

所以,今天我主要介绍命令行形式的抓包。

命令行抓包最基本的方式就是著名的tcpdump,不过我用得不是很多,所以就尽可能地“藏拙”了。

简单的抓包使用“-i lo”指定抓取本地环回地址,“port”指定端口号,“-w”指定抓包的存放位置,抓包结束时用“Ctrl+C”中断:

sudo tcpdump -i lo -w a.pcap
sudo tcpdump -i lo port 443 -w a.pcap

抓出的包也可以用tcpdump直接查看,用“-r”指定包的名字:

tcpdump -r a.pcap 
tcpdump -r 08-1.pcapng -A

不过在命令行界面下可以用一个更好的工具——tshark,它是Wireshark的命令行版本,用法和tcpdump差不多,但更易读,功能也更丰富一些。

tshark -r 08-1.pcapng 
tshark -r 08-1.pcapng -V
tshark -r 08-1.pcapng -O tcp|less
tshark -r 08-1.pcapng -O http|less

tshark也支持使用keylogfile解密查看HTTPS的抓包,需要用“-o”参数指定log文件,例如:

tshark -r 26-1.pcapng -O http -o ssl.keylog_file:26-1.log|less

tcpdump、tshark和Linux里的许多工具一样,参数繁多、功能强大,你可以课后再找些资料仔细研究,这里就不做过多地介绍了。

URI的查询参数和头字段

第11讲里我留了一个课下作业:

“URI的查询参数和头字段很相似,都是key-value形式,都可以任意自定义,那么它们在使用时该如何区别呢?”

从课程后的留言反馈来看,有的同学没理解这个问题的本意,误以为问题问的是这两者在表现上应该如何区分,比如查询参数是跟在“?”后面,头字段是请求头里的KV对。

这主要是怪我没有说清楚。这个问题实际上想问的是:查询参数和头字段两者的形式很相近,query是key-value,头字段也是key-value,它们有什么区别,在发送请求时应该如何正确地使用它们。

换个说法就是:应该在什么场景下恰当地自定义查询参数或者头字段来附加额外信息

当然了,因为HTTP协议非常灵活,这个问题也不会有唯一的、标准的答案,我只能说说我自己的理解。

因为查询参数是与URI关联在一起的,所以它针对的就是资源(URI),是长期、稳定的。而头字段是与一次HTTP请求关联的,针对的是本次请求报文,所以是短期、临时的。简单来说,就是两者的作用域和时效性是不同的。

从这一点出发,我们就可以知道在哪些场合下使用查询参数和头字段更加合适。

比如,要获取一个JS文件,而它会有多个版本,这个“版本”就是资源的一种属性,应该用查询参数来描述。而如果要压缩传输、或者控制缓存的时间,这些操作并不是资源本身固有的特性,所以用头字段来描述更好。

除了查询参数和头字段,还可以用其他的方式来向URI发送附加信息,最常用的一种方式就是POST一个JSON结构,里面能够存放比key-value复杂得多的数据,也许你早就在实际工作中这么做了。

在这种情况下,就可以完全不使用查询参数和头字段,服务器从JSON里获取所有必需的数据,让URI和请求头保持干净、整洁(^_^)。

今天的答疑就先到这里,我们下期再见,到时候再讲ECDHE算法。

unpreview

精选留言

  • 浪里淘沙的小法师

    2021-11-10 15:06:04

    讲一下用M1芯片 mac 搭建搭建环境的遇到的问题和解决方法。

    1. 运行 ./run.sh start 报错 /usr/local/bin/openresty: command not found
    这是因为 M1 芯片mac 的 homebrew 安装软件的位置与以往不同,先通过 which openresty 查询 openresty 的位置 /opt/homebrew/bin/openresty,然后打开 run.sh 脚本替换一下老师写的位置
    if [ $os != "Linux" ] ; then
    openresty="/usr/local/bin/openresty"
    fi
    替换成
    if [ $os != "Linux" ] ; then
    openresty="/opt/homebrew/bin/openresty"
    fi

    2. 再运行 ./run.sh start 报错 nginx: [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 32
    网上查寻了一下,放大 bucket_size 即可,打开 www/conf/nginx.conf 文件添加这一句server_names_hash_bucket_size 64; 即可
    # http conf
    http {
    #include http/common.conf;
    #include http/cache.conf;
    #include http/resty.conf;
    #include http/mime.types;
    server_names_hash_bucket_size 64;

    include http/*.conf;

    include http/servers/*.conf;

    }
    作者回复

    太高端了,都用上M1的Mac。

    也可以参考GitHub里的Dockerfile,构建出基于arm的镜像。

    2021-11-10 21:09:34

  • geekskai

    2019-10-09 00:24:59

    真好,又见到你了,而且我最近换个了mac,😊正愁这个。
    作者回复

    we meet again.

    2019-10-09 08:41:52

  • Luka!3055

    2020-05-07 22:23:52

    记录下问题:

    brew install openresty/brew/openresty 后,报错:
    curl: (7) Failed to connect to raw.githubusercontent.com port 443: Connection refused
    Error: An exception occurred within a child process:
    DownloadError: Failed to download resource "openresty-openssl--patch"
    Download failed: https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-1.1.0d-sess_set_get_cb_yield.patch

    此时把 DNS 设置为 114.114.114.114 或者 8.8.8.8 就好了,最好再挂个梯子
    作者回复

    nice

    2020-05-08 05:58:55

  • dongge

    2019-10-18 11:03:36

    老师好,
    按文章指导搭建了MAC的环境:
    openresty -v
    nginx version: openresty/1.11.2.2

    在~/git/http_study/www目录下执行
    ./run.sh start
    Password:
    nginx: [emerg] "/Users/xiaodong/git/http_study/www/conf/ssl/ticket.key" must be 48 bytes in /Users/xiaodong/git/http_study/www/conf/nginx.conf:34
    报了这个错误,在网上google没找到解决方法。
    尝试在nginx.conf中注销相关代码,也会报其他错误。
    老师能指点一下吗?
    作者回复

    这是提示Nginx要求48字节的密钥文件,按理说附带的80字节也是可以的,你可以用命令“openssl rand 48 > ticket.key”重新生成www/conf/ssl/ticket.key。

    详细可参见http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets

    另外,你用的openresty版本太老了,用最新的1.15.8.2可能就不会出现这样的问题。

    2019-10-18 14:47:11

  • dongge

    2019-10-16 14:46:30

    这个专栏这么好玩,留言的人这么少,真可惜。
    作者回复

    答疑篇来的太晚了,没赶上当初的热度,不过总会有需要的同学看到的。

    2019-10-16 16:37:21

  • ifelse

    2023-02-09 11:34:41

    谢谢分享
    作者回复

    my pleasure.

    2023-02-09 13:06:52

  • Change

    2020-03-28 10:35:46

    老师请教个问题:Mac 环境下安装以后,按照命令./run.sh start 启动后访问 localhost 显示403 Forbidden:终端返回的错误信息是下面的错误信息,这是所有端口都被占用了?我查了一下好像也没有被占用啊,不知道这是啥原因
    nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:8443 failed (48: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:440 failed (48: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:441 failed (48: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:442 failed (48: Address already in use)
    作者回复

    可能需要sudo,是否权限的问题。

    可以在网上搜一下错误信息,Nginx的问题一般都有现成的解决办法。

    2020-03-30 09:41:25

  • SmNiuhe

    2019-11-07 11:40:04

    这个大家有遇到嘛,是不是资源的问题
    brew install openresty/brew/openresty :DownloadError: Failed to download resource "openresty-openssl--patch"
    Download failed: https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-1.1.0d-sess_set_get_cb_yield.patch
    作者回复

    如果mac安装有问题,可以用virtualbox装个Linux虚拟机,暂解燃眉之急。

    2019-11-07 13:58:23

  • 努力变强

    2025-07-25 11:05:54

    M1芯片 mac 执行 brew install openresty/brew/openresty 报错解决:

    报错:
    checking for GeoIP library ... not found
    checking for GeoIP library in /usr/local/ ... not found
    checking for GeoIP library in /usr/pkg/ ... not found
    checking for GeoIP library in /opt/local/ ... not found
    checking for GeoIP library in /opt/homebrew/ ... not found
    ./configure: error: the GeoIP module requires the GeoIP library.
    You can either do not enable the module or install the library.

    ERROR: failed to run command: sh ./configure --prefix=/opt/homebrew/Cellar/openresty/1.27.1.2_1/nginx \...

    原因:
    缺少geoip库,geoip因为过期,brew下载不了

    解决方案:
    1. brew install geoip --force
    2. brew install openresty/brew/openresty
    完美解决!!


    作者回复

    amazing!

    2025-07-25 14:55:57

  • 火锅

    2025-04-14 23:10:26

    老师,我是m2芯片的mac,现在homebrew下载不了openresty,他提示需要GeoIP库,但是这个库在homebrew已经报废了,陷入死循环了,是不是只能去官网下载,我具体要怎么做
    作者回复

    建议用VMware安装Linux虚拟机来搭环境,mac比较小众,支持不完善很正常。
    另外也可以用Docker。

    2025-04-15 14:57:46

  • 超轶主

    2021-12-13 01:39:22

    mac环境运行 run run.sh 返回 nginx version: openresty/1.19.9.1
    format : run.sh [start|stop|reload|list]是什么情况呢
    作者回复

    后面要加参数,start|stop|reload|list。

    脚本比较简单,可以用vi看看。

    2021-12-13 11:40:57

  • silence

    2021-08-23 01:07:36

    请问安装好环境后在www目录执行./run.sh start 老是command not found怎么解决
    作者回复

    是不是没有安装好openresty,看看是哪个命令没找到,再按照课程正文是否遗漏了哪个步骤。

    2021-08-23 08:55:12

  • Miroticwillbeforever

    2021-06-22 23:15:55

    老师我有个问题。实验环境搭建好了。前两讲的实验也做成功了。
    但是当我用浏览器 访问 www.chrono.com 时,它跳转到的 地址为 https://dp.diandongzhi.com/?acct=660&site=chrono.com 然后wireshark抓包并没有任何反应。我想问一下是我操作不当的原因还是怎么回事。课程大部分听完了。但是后面实验没做成挺难受的,没有去验证。等老师给个答复准备二刷!
    作者回复

    域名解析这个问题确实困扰了不少同学,因为我们实验环境的域名是假的,只能在本地用,所以有可能会与某些真实的域名冲突,导致输入域名跑到了外网而不是实际环境。

    解决方法是改hosts文件,但因为域名会有缓存,所以有时候改了hosts也不会生效。如果遇到这种情况,最好是换个实验环境,改成虚拟机或者docker。

    2021-06-23 09:38:00

  • 武安君

    2021-03-20 09:27:01

    老师你好、我安装好了openrestry后、启动服务说 nginx:invalid option:http,请问是怎么回事呀
    作者回复

     这个提示信息太模糊了,不好帮你。

    可以网上搜一下错误信息,一般都能找到解决方案。或者把OpenResty、GitHub项目重新安装看看。

    还是不行就改用docker试试。

    2021-03-20 21:12:15

  • 小童

    2021-03-02 17:30:39

    不行啊,老师,我的那个openresty界面出来了,就是抓不到包!用的wireshark .搞了好久。那个telnet也安装了。是不是那步出错了 ,我就直接运行openresty,然后用抓包工具过滤信息,然后浏览器输入localhost,浏览器洁界面也出来了。
    作者回复

    可以先试试Wireshark能不能抓其他网络的包,然后再试试抓本地(loopback),再加上过滤器,逐步分析来缩小范围。

    如果还不行,可以试着换个环境,用虚拟机+Linux或者docker,这样的环境比较单纯隔离。

    2021-03-03 09:23:24

  • 旗木卡卡

    2020-08-19 22:54:00

    Mac电脑,耗费本人2个晚上的环境,终于搭好了,碰到了2个坑,第一个是dns查找不到,brew install openresty时,需要在本机的hosts文件,加上解析不到的url的ip地址,第二个是启动一直bind不上,nginx就自动启动了,但是很明显不是openresty,然后用root权限启动成功,也可以正常访问,发现是nginx.conf的user权限问题,修改成本机的用户user kaka(你的用户名) staff;即可。
    作者回复

    虽然都是unix,但mac的环境和Linux还是不太一样,辛苦了。

    2020-08-20 08:54:40

  • Jinlee

    2020-04-21 20:56:46

    Welcome to HTTP Study Page! 还好我看得迟,成功在ubuntu下搭建起环境😊😊😊
    作者回复

    nice

    2020-04-22 06:20:21

  • 神经旷野舞者

    2020-01-06 01:23:29

    最喜欢实验环境了,之前学习就是苦于没实验环境浪费了几年时间。
    作者回复

    搭好后一定要多做实验,实践出真知。

    2020-01-06 09:01:39

  • 无名

    2019-11-15 09:44:37

    Updating Homebrew...
    ==> Auto-updated Homebrew!
    Updated 1 tap (homebrew/core).
    ==> Updated Formulae
    handbrake

    ==> Installing openresty from openresty/brew
    ==> Downloading https://openresty.org/download/openresty-1.15.8.2.tar.gz
    Already downloaded: /Users/hejunbin/Library/Caches/Homebrew/downloads/4395089f0fd423261d4f1124b7beb0f69e1121e59d399e89eaa6e25b641333bc--openresty-1.15.8.2.tar.gz
    ==> ./configure -j8 --prefix=/usr/local/Cellar/openresty/1.15.8.2 --pid-path=/us
    Last 15 lines from /Users/hejunbin/Library/Logs/Homebrew/openresty/01.configure:
    DYNASM host/buildvm_arch.h
    HOSTCC host/buildvm.o
    HOSTLINK host/buildvm
    BUILDVM lj_vm.S
    BUILDVM lj_ffdef.h
    BUILDVM lj_bcdef.h
    BUILDVM lj_folddef.h
    BUILDVM lj_recdef.h
    BUILDVM lj_libdef.h
    BUILDVM jit/vmdef.lua
    make[1]: *** [lj_folddef.h] Segmentation fault: 11
    make[1]: *** Deleting file `lj_folddef.h'
    make[1]: *** Waiting for unfinished jobs....
    make: *** [default] Error 2
    ERROR: failed to run command: gmake -j8 TARGET_STRIP=@: CCDEBUG=-g XCFLAGS='-msse4.2 -DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT' CC=cc PREFIX=/usr/local/Cellar/openresty/1.15.8.2/luajit

    If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):
    https://github.com/openresty/homebrew-brew/issues

    These open issues may also help:
    Can't install openresty on macOS 10.15 https://github.com/openresty/homebrew-brew/issues/10
    Fails to install OpenResty https://github.com/openresty/homebrew-brew/issues/5
    The openresty-debug package should use openresty-openssl-debug instead https://github.com/openresty/homebrew-brew/issues/3

    macOS 10.15.1 安装失败。参考给出的链接也没有解决问题,求老师解惑。
    作者回复

    10.15是新出的,我没升级,看这些信息像是openresty在这上面安装有问题(luajit编译失败),可以向官方反应一下,只能期待官方更新包了。

    2019-11-15 10:12:17

  • Dream.

    2019-10-17 22:28:00

    Linux-CentOS 7下,修改了/etc/hosts的域名与IP的映射关系后

    再使用./run.sh start启动OpenResty之后

    curl localhost 或者 curl http://www.chrono.com都是返回403

    按之前课程里的url访问https://www.chrono.com/11-1什么的,都返回404

    第一次接触OpenResty,麻烦老师回复下是哪里没配置好嘛?
    作者回复

    我这里没有遇到你这样的现象。

    先用run.sh list看看Nginx进程是否正常运行,然后用netstat等工具检查一下监听端口,是否有防火墙什么的其他应用阻碍了服务。

    可以问问周围熟悉Linux运维的同事。

    2019-10-18 08:49:20