최근 개발 관련 프로젝트를 진행하다보니, 한 가지 개선을 했으면 하는 점이 하나 생겼다.
지금까지는 필자가 Linux 용으로 개발한 결과물을 단순히 tar 파일로 묶어 배포하는 방식을 사용해왔는데, 이 방식을 사용하면, 필자의 프로그램이 참고하는 config 파일과 log 파일 등을 Linux에서 권장하는 경로에 위치시키려면 설치 과정이 복잡해진다는 단점이 나타난 것이다(보통 Linux에 설치되는 프로그램의 설정파일은 /etc 폴더에, 로그 파일은 /var/log 폴더에 위치하고 있음을 생각해보자)
물론 tar 파일 내에 config나 log파일을 저장하는 폴더를 만들고 필자의 프로그램이 그 폴더들을 참고하게 만드는 것도 나쁘지 않지만, 개인적으로 사용하는 프로그램이면 모를까... 필자가 만든 프로그램을 오픈 소스로 글로벌하게 사용할 수 있게 하나 만들어보는 것이 위시 리스트의 하나인 상태에서는 계속 기존 방식을 고수하기에도 성에 차지 않는다.
이러한 이유로 이번 포스팅에서는 RPM 패키지의 생성과 설치 방법에 대한 내용을 작성하려 한다. RPM 패키지을 만들 일은 많이 없지만 정리해놓으면 언젠가는 잘 사용할테니 말이다.
** RPM과 관련된 기본 명령어 사용법은 아래의 두 포스팅을 참고하자.
참고로 필자가 포스팅에 사용했던 CentOS7은 이제 구식이 되어 버려서(벌써?) 새로 CentOS8에서 테스트를 진행하고 있다.
1. RPM Build 관련 패키지 설치
RPM 패키지를 생성(RPM Build라고 한다)를 위해서 필요한 패키지는 아래와 같다.
패키지명 | 설명 |
rpm-build | rpmbuild 명령어를 포함하는 기본 패키지. RPM 파일 Build를 위해 필수로 설치되어 있어야 한다. |
rpmdevtools | RPM Build에 필요한 파일 구조를 생성해주는 rpmdev-setuptree 등 RPM 생성을 지원하는 도구가 존재하는 패키지다. |
다른 패키지로 rpm-devel과 rpmlint라는 패키지도 존재하는데, 이들은 지금 단계에서는 크게 볼 것이 없는 것이니 추후 시간이 되면 포스팅하려한다.
패키지 설치는 아래의 명령어로 진행하자.
# sudo yum install -y rpm-build rpmdevtools
설치가 완료되면 rpmbuild 및 rpmdev-setuptree 명령어를 사용할 수 있게 된다. 여기까지 확인되면 다음 단계로 넘어가자.
2. RPM Build 환경 구축
RPM 패키지를 생성하기 위해 선행되어야 하는 일이 하나 있다. 바로 RPM 패키지에 필요한 파일 구조를 미리 만들어주어야 한다는 것이다.
RPM 패키지 생성을 위한 파일 구조는 아래와 같다.
- BUILD : rpm 패키지 생성 시 소스코드 관련 작업이 진행되는 폴더
- RPMS : 생성된 rpm 패키지(binary)가 존재하는 폴더
- SOURCES : rpm 패키지 생성에 사용하는 소스가 위치하는 폴더
- SPECS : rpm 패키지 생성에 사용하는 spec 파일이 위치하는 폴더
- SRPMS : 생성된 rpm 패키지(source)가 존재하는 폴더
폴더가 5개 밖에 되지 않지만, rpm을 하나 만들때마다 이 폴더들을 일일이 명령어를 쳐서 만들어주기가 영 불편한 것이 아니다. 이러한 불편함 때문에 보통 rpm 패키지 생성 환경을 구축할 때 rpmdev-setuptree라는 명령어를 사용한다.
rpmdev-setuptree 명령어의 특이한 점은 어떠한 옵션이나 인자도 없다는 것과, 명령어 실행 시 현재 접속중인 계정의 home 폴더에만 rpmbuild라는 이름의 폴더를 생성한다는 것이다. 물론 rpmbuild 폴더 내에는 rpm 패키지 생성에 필요한 폴더들이 자동 으로 생성되어 있고 말이다.
이제, 구축한 환경에 넣을 spec과 쉘 스크립트 파일을 생성해보자.
3. RPM Build를 테스트 스크립트 생성
(1) 명령어로 사용할 스크립트 파일 생성
필자는 myscript-1.0.sh라는 이름의 스크립트를 하나 만들어보려한다. 이 스크립트를 실행하면 단순히 Hello World라는 문구가 화면에 출력되도록 만들 것이다.
이제 필자는 이 스크립트 파일을 명령어로 변경하려한다. 단, 단순히 명령어만 만드는 것이 아니라, rpm 파일 내에 명령어 파일을 집어넣고, rpm 설치 시 rpm build 시 포함된 이 명령어가 /usr/bin이나 기타 명령어 폴더에 바로 위치하도록 만들어보려한다.
(2) RPM Build를 위한 Spec 파일 생성
linux에서 .spec 확장자를 가지는 파일은 RPM Build를 위한 설정 파일인 경우가 많다(필자가 "많다 "라고 표현한 것은 Python의 pyinstaller 패키징 결과물로 나오는 .spec 확장자 파일도 있기 때문이다. 이는 본 포스팅 내용과 관계가 없다).
이 .spec 파일은 Linux의 .service 파일처럼 RPM Build를 위한 이런 저런 설정이 포함되게 된다.
아래의 사진을 보자.
위 내용은 rpm package 생성을 위해 필요한 spec 파일의 기본 내용이다. 이 spec 파일의 내용을 보면 만들고자 하는 RPM의 이름, 버전, Release나 설명 외에도, rpm의 설치/삭제 시 동작도 이 파일에 지정할 수 있도록 되어 있음을 알 수 있다. 정리하자면, rpmbuild 명령어는 이 spec 파일의 내용을 통해, rpm에 추가할 파일, 설치 시 동작, 삭제 시 동작을 참고하여 rpm 파일을 생성하게 되는 것이다.
spec 파일의 설정 변수들을 보면 변수명 앞에 %가 붙은 변수도 있고, 그렇지 않은 변수도 있음을 확인할 수 있는데
%가 없는 변수들은 속성(attribute)이라고 하며, %가 변수명 접두에 추가된 것들은 rpm의 지시자(directives)라고 한다.
① 속성 변수 종류
속성은 Name, Version, Release, Summary 등 사용자가 직접 지정하는 값들로 구성되어 있다. 종류는 아래와 같다.
속성명 | 설명 |
Name | rpm 패키지의 이름 지정 |
Version | rpm 패캐지의 Minor, Major 버전 지정 |
Release | rpm 패키지의 Release 횟수 (Patch Version과 유사한 개념이라고 보면 된다) |
Summary | rpm 패키지에 대한 간략한 설명 |
License | rpm 패키지에 사용된 Software 라이선스 지정. 존재하지 않는 라이선스 입력 시, rpmbuild가 진행되지 않는다. |
URL | rpm 패키지에 대한 설명이 수록된 Webpage URL 입력 |
Source0 | rpm 패키지 Build에 사용할 소스 파일 경로 지정. |
BuildRequires | rpm 패키지가 Build 또는 실행 시 필요로 하는 Dependencies 지정. |
Requires |
필수적으로 Name, Version, Release, Source0, License는 반드시 입력되어야하며, 나머지 속성은 입력할 값이 없으면 삭제하면 된다. 공란을 허용하지 않으니 주의하자.
위의 내용을 참고하여 spec 파일의 속성을 채우면 아래와 같은 내용이 완성된다.
② 지시자 변수 종류
지시자는 일반 속성과 달리 %가 앞에 붙어 있다. 일반 속성과 달리 이들은 RPM 패키지가 어떻게 동작해야하는지에 대한 작업 지침을 작성하는 부분이라보면 된다.
spec 파일에서 사용하는 지시자의 종류는 아래와 같다.
속성명 | 설명 |
%Description | rpm 패키지에 대한 간략한 설명 입력 |
%prep | rpm 패키지 build 전 사전 작업이 필요한 경우 사전 작업 내용을 입력 보통 Source0 에 명시된 파일이 tar.gz으로 묶여있는 상태인 경우, 파일 압축 해제 등에 사용한다. |
%build | source 의 compile과 build 에 필요한 작업 내용을 입력한다. |
%install | rpm 패키지 생성 시 rpm 에 포함시키고자 하는 파일을 임시 디렉토리에 어떻게 구성할 것인지 지정한다. |
%files | 생성한 rpm 패키지가 -ivh로 설치될 때, rpm 내부에 포함된 파일을 지정할 위치를 명시한다. |
%changelogs | rpm 패키지 개발 관련 변경 사항 발생 시, 수정 작업자가 직접 로그를 기록한다. rpm --changelogs 명령어 사용 시 나타나는 내용이다. |
현재 필자는 단순히 스크립트 파일만 rpm 에 포함시킬 예정이기 때문에 %prep, %build에 대한 내용은 추가할 이유가 없다. 따라서 아래와 같이 지시자 내용을 작성하려 한다.
%install 부분을 보면 rpm 패키지 생성 시 동작을 확인할 수 있는데, rpmbuild 폴더 내에 BUILDROOT/myscript1.0.1.x86_64/usr/bin 폴더를 만들고, 해당 폴더에 SOURCES에 위치한 쉘 스크립트 파일의 install 결과물을 저장한다는 의미다. 결과물로 BUILDROOT 내에는 /usr/bin/myscript라는 파일이 생성되며, myscript은 %files 지시자에 의해 rpm 설치 시, /usr/bin/myscript에 위치하게 된다.
경로를 잘 보면 BUILDROOT라는, rpmbuild 폴더에 전혀 존재하지 않는 이름이 보이는데, 이 폴더는 rpmbuild 명령어 실행 시 rpmbuild 폴더 내에 신규로 생성되는 폴더다. 이 폴더는 %install에 의해 rpm 패키지 생성 과정이 진행되는 동안 작업 공간으로 활용된다.
이제 생성한 spec 파일과 쉘 스크립트 파일을 각각 rpmbuild/SPECS와 rpmbuild/SOURCES로 이동시키자.
4. rpmbuild로 rpm 패키지 생성
이제 본격적으로 rpm 패키지 생성을 진행해보자. rpm 패키지 생성은 rpmbuild라는 명령어를 spec 파일 경로와 함께 사용하면 되며, 기본적으로 binary와 source rpm을 동시에 생성하는 옵션인 -ba를 사용한다.
# 명령어: rpmbuild -ba rpmbuild/SPECS/myscript.spec
정상적으로 build가 완료되면 마지막에 +exit이라는 문구와 함께 프롬프트가 떨어진다. tree를 사용하여 rpmbuild 폴더의 파일 구조를 보면 아래와 같이 binary 형태의 rpm파일과 source 형태의 rpm 파일이 생성된 것을 확인할 수 있다.
5. 생성한 rpm 패키지의 동작 검증
이제 생성한 rpm파일을 linux에 설치하고 필자가 원하는 대로 동작하는지 확인해보자.
생성한 rpm 패키지 파일을 복사하여 홈 폴더에 놓고 설치를 진행하기 전, myscript라는 이름의 명령어가 존재하는지 확인해보자.
명령어가 존재하지 않는 것을 확인했으니, 이제 rpm 설치 후 명령어가 존재하는지, 제대로 동작하는지 확인해보자.
당연하지만 설치된 myscript rpm 패키지를 삭제하면 다시 명령어를 사용할 수 없게 된다.
rpm 패키지 생성을 배우기 전에 가장 먼저 확인해야하는 부분이 바로 rpm 패키지 생성 환경의 폴더 구조와 역할인 듯 하다. 필자는 service처럼 단순할 것이라 생각하고 안일하게 spec 파일 테스트만 진행하다가 시간을 많이 잡아먹었는데, 폴더 구조와 역할에 대해 먼저 파악했더라면 spec 파일 관련 내용도 머리 싸메는 일 없이 잘 마무리되지 않았을까 싶다(오늘 spec 파일 때문에 Chat GPT를 엄청나게 괴롭혔다...)
그런데, 필자가 위에서 진행한 방식은 문제가 한 두 가지가 아니다. 먼저, 하나 이상의 rpm 패키지 생성을 진행하게 된다면, rpmbuild 폴더를 공유할 수 없다는 문제가 발생한다. 필자가 사용했던 rpmbuild 명령어는 특정 옵션이 없다면 무조건 Home 폴더의 rpmbuild만 바라보게 되어 있기 때문에 다른 rpm 패키지를 생성하려면 rpmbuild 내 폴더 전체를 싸그리 비워줘야 한다는 문제가 생긴다. 즉, 개별 RPM에 대한 버전 관리가 불가능해지는 상황이 발생한다는 이야기다.
두 번 째로, spec 파일에 명시된 버전, 경로 중 하나라도 수정이 된다면 해당 값들을 변경해야하는 포인트가 늘어나기 때문에 관리 상의 에러가 발생한다. 지금이야 필자가 테스트라 %install 섹션의 내용을 간단하게 만들어서 그렇지.. 이 내용이 복잡해지면 분명 한 두 군데 변경을 누락하는 현상이 발생할 것이다.
이들의 문제점을 해결할 수 있는 방법은 다음 포스팅에서 알아보려 한다. 언제 작성할 수 있을지는 모르겠다만..
Fin.
'IT Security > LINUX Basic' 카테고리의 다른 글
44. Linux 방화벽 제어 - firewall-cmd 개요 (0) | 2024.03.03 |
---|---|
43. Linux rpm 파일 만들기2 - spec 파일 macros 및 rpm 관리 (0) | 2023.08.14 |
41. Linux chroot 사용법 (0) | 2022.05.06 |
40. Linux - 나만의 Service를 만들어 구동해보자2 (0) | 2021.09.25 |
39. Linux - 나만의 Service를 만들어 구동해보자1 (0) | 2021.09.24 |
댓글