Post

nginx build

목차


초간단 nginx 빌드 방법

nginx 내부 소스를 조금 수정하여 빌드해야 할 일이 생겨 기록하게 되었다.

소스 다운로드

링크 : http://nginx.org/en/download.html

아래 링크에서 알맞는 버전의 소스를 다운로드 할 수 있도록 하자.

또는 링크를 수정하여 다운로드 할 수 있다.

1
wget --no-check-certificate http://nginx.org/download/nginx-1.18.0.tar.gz

필자는 nginx -v 를 쳤을 때 기존에 apt로 설치된 nginx의 버전이 1.18.0 버전이었던 관계로 1.18 버전으로 진행하였다.

1
2
# nginx -v
nginx version: nginx/1.18.0 (Ubuntu)

./configure 작성

빌드 환경

1
2
3
4
5
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.5 LTS
Release:        20.04
Codename:       focal

압축파일을 풀어 configure 옵션을 지정한다.

옵션이 많을 수 있으니 따로 배쉬 스크립트 파일 등을 만들어 진행하는 게 좋을 것이다.

build 옵션 문서 : http://nginx.org/en/docs/configure.html

만약 openssl 버전을 지정해야 한다면 문서를 참조하자.

1
2
3
4
5
# nginx -V
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 1.1.1f  31 Mar 2020
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-lUTckl/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-compat --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module

필자는 기존에 설치된 nginx의 컴파일 옵션을 그대로 줘서 진행했다.

build.sh 파일을 만들고 실행권한을 준 뒤 옵션을 기입하고 알맞게 수정한다.

``–with-cc-opt` 에서 원래 -O2 (Optimizer 컴파일 최적화 옵션 2단계) 진행되었으나
필자의 경우 디버깅을 위해 -O0 (컴파일 최적화 옵션 사용 안함) 으로 수정하였다.

이외 아래 내용과 같이 특정 라이브러리가 설치되지 않았다는 오류가 있어 설치하여 해결하였다.

1
2
3
4
5
6
7
8
9
10
./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.

./configure: error: the HTTP XSLT module requires the libxml2/libxslt
libraries. You can either do not enable the module or install the libraries.

./configure: error: the HTTP image filter module requires the GD library.
You can either do not enable the module or install the libraries.
1
2
3
4
5
6
7
8
# pcre
apt-get -y install libpcre libpcre-dev
# libxml
apt-get -y install libxml2 libxml2-dev
# libxslt
apt-get -y install libxslt1.1 libxslt1-dev
# libgd
apt-get -y install libgd-dev

라이브러리는 아마 대체로 /usr/lib/x86-64-linux-gnu 에 있을 것이다. 이외에는 find 명령어로 직접 찾아보기 바란다.

최종적으로 작성한 build.sh 는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash

# --with-pcre=/usr/lib/x86_64-linux-gnu/libpcre.so \
# --prefix=/etc/nginx \
./configure \
    --with-cc-opt='-g -O0 -fdebug-prefix-map=/build/nginx-lUTckl/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' \
    --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' \
    --sbin-path=/usr/sbin/nginx \
    --prefix=/usr/share/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --http-log-path=/var/log/nginx/access.log \
    --error-log-path=/var/log/nginx/error.log \
    --lock-path=/var/lock/nginx.lock \
    --pid-path=/run/nginx.pid \
    --modules-path=/usr/lib/nginx/modules \
    --http-client-body-temp-path=/var/lib/nginx/body \
    --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
    --http-proxy-temp-path=/var/lib/nginx/proxy \
    --http-scgi-temp-path=/var/lib/nginx/scgi \
    --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
    --with-debug \
    --with-compat \
    --with-pcre \
    --with-pcre-jit \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_realip_module \
    --with-http_auth_request_module \
    --with-http_v2_module \
    --with-http_dav_module \
    --with-http_slice_module \
    --with-threads \
    --with-http_addition_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_image_filter_module=dynamic \
    --with-http_sub_module \
    --with-http_xslt_module=dynamic \
    --with-stream=dynamic \
    --with-stream_ssl_module \
    --with-mail=dynamic \
    --with-mail_ssl_module

configure 진행이 끝나면 아래와 같은 출력결과를 볼 수 있을 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
creating objs/Makefile

Configuration summary
  + using threads
  + using PCRE library: /usr/lib/x86_64-linux-gnu/libpcre.so
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/usr/share/nginx"
  nginx binary file: "/usr/share/nginx/sbin/nginx"
  nginx modules path: "/usr/lib/nginx/modules"
  nginx configuration prefix: "/etc/nginx"
  nginx configuration file: "/etc/nginx/nginx.conf"
  nginx pid file: "/run/nginx.pid"
  nginx error log file: "/var/log/nginx/error.log"
  nginx http access log file: "/var/log/nginx/access.log"
  nginx http client request body temporary files: "/var/lib/nginx/body"
  nginx http proxy temporary files: "/var/lib/nginx/proxy"
  nginx http fastcgi temporary files: "/var/lib/nginx/fastcgi"
  nginx http uwsgi temporary files: "/var/lib/nginx/uwsgi"
  nginx http scgi temporary files: "/var/lib/nginx/scgi"

Make

컴파일 진행

1
make -j8

성공적으로 진행되었을 시 objs/ 내 파일들이 보일 것이다.

1
make install

명령어를 통해 설치를 진행할 수 있다.

DEBUG

기존 nginx 죽이는 쉘 스크립트 작성

kill_nginx.sh (chmod 755)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

PROCESS=nginx

while [ : ]; do

pid_result=$(pidof $PROCESS)
if [[ "$pid_result" = "" ]]; then
    echo "$PROCESS is not running"
    break
fi

pkill -f "$PROCESS:"
echo "kill $PROCESS process"

done

start.sh 스크립트 작성 (chmod 755)

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash

curpath=$(dirname $(realpath $0))
cd $curpath

./kill_nginx.sh

echo "$PROCESS start"
# /usr/sbin/nginx

./objs/nginx

gdb 없으면 설치하고

1
apt-get install gdb

필자는 vscode로 디버깅 진행할 것이기 때문에
launch.json과 tasks.json 등을 맞춰줌

현재 필자의 ${workspaceFolder:nginx} 경로는 ~/nginx/src/ 이기 때문에
~/nginx/objs/ 경로를 맞춰주기 위해 ../ 설정

각자의 세팅에 알맞게 설정 바람

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
nginx (project dir)
- auto/
- conf/
- contrib/
...(중략)...
- objs/
    - nginx (execute file)
- src/
    - source
    - .vscode/
        + nginx.code-workspace
            - workspace 내 folder 설정은 다음과 같이 진행함
	            "folders": [
	            	{
	            		"name": "nginx",
	            		"path": "../"
	            	},
	            ],
        + tasks.json
        + launch.json
+ build_nginx.sh
+ kill_nginx.sh
+ start.sh

launch.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{
	"version": "0.2.0",
	"configurations": [
		{
			"name": "nginx",
			"type": "cppdbg",
			"request": "launch",
			"program": "${workspaceFolder:nginx}/../objs/nginx",
			"args": [],
			"stopAtEntry": false,
			"cwd": "${workspaceFolder:nginx}",
			"environment": [],
			"externalConsole": false,
			"MIMode": "gdb",
			"showDisplayString": true,
			"setupCommands": [
				{
					"description": "gdb에 자동 서식 지정 사용",
					"text": "-enable-pretty-printing",
					"ignoreFailures": true
				},
				{
					"description": "SIG34 무시",
					"text": "handle SIG34 nostop noprint pass",
					"ignoreFailures": true
				},
				{
					"description": "SIG33 무시",
					"text": "handle SIG33 nostop noprint pass",
					"ignoreFailures": true
				},
				{
					"description": "문자열 1000자 이상은 자르기",
					"text": "set print elements 1000",
					"ignoreFailures": true
				},
				{
					"description": "어셈블리 코드 인텔 스타일 사용",
					"text": "set disassembly-flavor intel",
					"ignoreFailures": true
				},
				{
					"description": "자식 프로세스 디버깅 (worker process debuging)",
					"text": "set follow-fork-mode child",
					"ignoreFailures": true,
				},
			],
			// breakpoint 중첩되는것 제거
			"sourceFileMap": {
				"${workspaceFolder}": {
					"editorPath": "${workspaceFolder:nginx}",
					"useForBreakpoints": "true"
				},
			},
			"preLaunchTask": "nginx kill",
			// gdb 통신 로그 확인
			// "logging": {
			// 	"engineLogging": false,
			// 	"exceptions": false,
			// 	"moduleLoad": false,
			// 	"programOutput": true,
			// 	"trace": false,
			// 	"traceResponse": false,
			// },
		},
	],
}

tasks.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "shell",
			"label": "nginx kill",
			"command": "${workspaceFolder:nginx}/../kill_nginx.sh",
			"args": [ ],
			"options": {
				// "cwd": "${workspaceFolder:nginx}/../"
			},
			"problemMatcher": [
				"$gcc"
			],
			"presentation": {
				"revealProblems": "onProblem",
				"close": true
			}
		}
	]
}

ngx_daemon.c 파일에 printf 문 하나 만들어준 뒤 중단점 찍고 디버깅 해봄

정상적으로 breakpoint 걸림

그런데 왜 헤더를 못찾냐

./ngx_auto_config.h ./ngx_auto_headers.hobjs/ 디렉토리에 있어서 그렇군..

c_cpp_properties.json 를 다음과 같이 수정했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder:nginx}/**",
                "${workspaceFolder:nginx}/../objs/*",
                "/usr/include/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu11",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "linux-gcc-x64",
            "configurationProvider": "ms-vscode.cmake-tools"
        }
    ],
    "version": 4
}

worker process 디버깅을 진행하고 싶으면 set follow-fork-mode child 옵션을 주고
(필자가 적은 launch.json 에는 해당 옵션 존재)

nginx.conf 에서 아래 옵션을 줘 worker process를 하나로 세팅한 뒤 진행하는 것이 디버깅하기 편할 것이다.

1
worker_processes 1;

worker process 에 breakpoint가 잡힌 상태

This post is licensed under CC BY 4.0 by the author.