LabHub
배우기 러닝패스 코스

パッケージ管理

dpkgはグラフを解かない

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

apt 는 무엇을 설치할지 정하는 도구이고, dpkg 는 정해진 것을 설치하는 도구다. 이 분업을 알면 dpkg -i 가 왜 의존성 에러로 멈추는지 바로 이해된다.

概念マップ: 무엇을 설치할지 정하는 도구・정해진 것을 설치하는 도구・unpack → configure・rc 상태를 못 보고 지나가는 일이 흔하다.

왜 이게 필요했나

.deb 파일 하나를 받아 dpkg -i 로 설치하면 이런 메시지가 나온다.

dpkg: dependency problems prevent configuration of labhub-extra:
 labhub-extra depends on labhub-tool (>= 1.2.0); however:
  Package labhub-tool is not installed.

dpkg 는 저장소를 모른다. 어디서 무엇을 받아 와야 하는지도 모른다. 그저 주어진 파일을 풀고, 의존이 만족되지 않으면 "설정되지 않음" 상태로 남겨 둘 뿐이다. 그래서 apt-get -f install(fix broken)이 짝으로 존재한다. 이건 "dpkg 가 남긴 미해결 상태를 apt 가 저장소를 보고 마저 풀어라" 는 뜻이다.

어떻게 동작하나

.deb 파일은 사실 ar 아카이브다. 안에 세 조각이 들어 있다.

조각 내용
debian-binary 형식 버전 (보통 2.0)
control.tar.* control 파일과 유지보수 스크립트(preinst/postinst/prerm/postrm), conffiles, md5sums
data.tar.* 실제로 파일시스템에 풀릴 파일들

설치는 unpack → configure 두 단계다. unpack 은 data 를 푸는 것이고, configure 는 postinst 를 실행해 서비스를 등록하는 등의 마무리를 하는 것이다. dpkg -l 출력의 앞 두 글자가 이 상태를 나타낸다.

표시
ii 설치 요청 + 설치 완료 (정상)
iU 설치 요청 + unpack 만 됨 (configure 실패)
rc 제거 요청 + 설정 파일만 남음
pn 미설치 (purge 됨)

rc 상태를 못 보고 지나가는 일이 흔하다. "지웠는데 왜 설정이 남아 있지?" 의 정답이 여기 있다.

dpkg 의 조회 명령은 세 방향이다.

dpkg -l                       # 무엇이 설치돼 있나
dpkg -L coreutils             # 이 패키지가 어떤 파일을 깔았나
dpkg -S /usr/bin/ls           # 이 파일은 누가 깔았나
dpkg -s coreutils             # 이 패키지의 메타데이터는 무엇인가
dpkg-query -W -f='${Package} ${Version}\n'

세 번째(-S)가 실전에서 제일 자주 쓰인다. 낯선 서버에서 정체불명의 바이너리를 만났을 때, 그것이 패키지가 깐 것인지 사람이 손으로 놓은 것인지를 1초 만에 가른다. dpkg -S 가 아무것도 못 찾으면 그 파일은 패키지 관리 밖에 있는 것이고, 그런 파일은 업그레이드 때 사라지지 않고 백업에도 안 잡히기 쉽다.

현장에서 만나는 모습

설정 파일 충돌. 업그레이드 중 Configuration file '/etc/foo.conf' ... What would you like to do? 프롬프트가 뜬다. dpkg 는 conffiles 에 등록된 파일의 md5 를 기억하고 있어서, 사람이 고쳤는지 알아낸다. 이 프롬프트에서 무심코 "package maintainer's version" 을 고르면 손으로 넣은 튜닝이 통째로 사라진다. 자동화 스크립트에서는 -o Dpkg::Options::="--force-confold" 로 정책을 명시해야 한다.

설정 파일은 특별하게 다뤄진다

.deb 안의 conffiles 에 적힌 파일은 나머지와 다른 규칙을 받는다. 이 규칙을 모르면 갱신 뒤에 설정이 사라졌다거나 반대로 새 설정이 안 들어왔다는 상황을 만나고, 둘 다 원인이 같다.

dpkg 는 갱신할 때 세 가지를 비교한다. 패키지가 처음 넣었던 내용, 지금 디스크에 있는 내용, 그리고 새 패키지가 넣으려는 내용이다.

세 번째가 문제의 자리다. 자동화된 갱신에서는 아무도 그 질문을 못 보므로, 새 버전이 요구하는 설정 항목이 우리 파일에 없는 채로 서비스가 돈다. 조용히 기본값으로 동작하다가 나중에 이상한 증상으로 나타난다. 그래서 갱신 뒤에 .dpkg-dist·.dpkg-new·.ucf-dist 가 생겼는지 훑는 절차가 필요하다.

rc 상태와 설정 파일의 관계도 여기서 설명된다. 앞에서 본 대로 지워도 설정이 남는 이유가 removeconffiles 를 건드리지 않기 때문이고, purge 가 그것까지 지운다. 그래서 같은 패키지를 다시 깔면 옛 설정이 되살아나고, "깨끗하게 다시 깔았는데 같은 문제가 난다" 가 여기서 나온다.

마지막으로 설정 파일을 패키지 밖에서 관리할 생각이라면 아예 conffiles 에 없는 별도 파일로 두는 편이 낫다. 대부분의 패키지가 conf.d/ 같은 디렉터리를 두는 이유가 이것이다. 그 안의 파일은 패키지 소유가 아니므로 갱신이 건드리지 않고, 세 방향 비교 자체가 일어나지 않는다.

다음 실습에서 할 것

dpkg -L/-S/-s 로 시스템을 조회하고, 픽스처 디렉터리에서 직접 .deb 를 빌드해 설치까지 해 본다. 패키지를 만들어 보면 그 안에 무엇이 있는지 확실히 알게 된다.