Traceback (most recent call last):
File "/usr/bin/dnf", line 57, in <module>
from dnf.cli import main
ModuleNotFoundError: No module named 'dnf'
RHEL 8 이상에서 yum 은 dnf 로 가는 심볼릭 링크이므로 yum 을 실행해도 같은 오류가 난다. 패키지 관리자가 죽은 상태라 패키지 관리자로 고칠 수 없다는 점이 이 장애의 핵심이다. rpm 으로 직접 복구한다.
/usr/bin/dnf 는 파이썬 스크립트이고, 첫 줄의 인터프리터로 dnf 파이썬 모듈을 불러온다. 다음 중 하나가 깨졌다.
head -1 /usr/bin/dnf
#!/usr/bin/python3
| 원인 | 확인 |
|---|---|
python3-dnf 패키지가 지워짐 |
rpm -q python3-dnf python3-libdnf python3-hawkey |
| shebang 이 가리키는 인터프리터가 없음 | ls -l /usr/bin/python3 /usr/libexec/platform-python |
/usr/bin/python 을 직접 만든 링크로 덮음 |
ls -l /usr/bin/python* |
소스 빌드한 파이썬이 /usr/bin 을 덮어씀 |
which -a python3 |
pip 로 시스템 파이썬에 설치하다 의존 패키지를 밀어냄 |
pip3 list |
가장 흔한 것은 마지막 두 가지다. 애플리케이션 요구로 파이썬을 새로 빌드해 /usr/bin/python3 를 바꿔 끼우거나, sudo pip3 install --upgrade 로 시스템 파이썬 패키지를 갈아엎으면 이렇게 된다.
RHEL 8 의 dnf 는 일반 python3 가 아니라 /usr/libexec/platform-python 을 쓰도록 되어 있다. 이 분리는 사용자가 파이썬을 바꿔도 OS 도구가 살아 있게 하려는 것인데, shebang 을 손대면 의미가 없어진다.
/usr/libexec/platform-python /usr/bin/dnf --version
이것이 동작하면 모듈은 멀쩡하고 shebang 만 잘못된 것이다. 원래대로 되돌린다.
sudo sed -i '1s|.*|#!/usr/libexec/platform-python|' /usr/bin/dnf
sudo sed -i '1s|.*|#!/usr/libexec/platform-python|' /usr/bin/dnf-3
RHEL 9 이상은 /usr/bin/python3 를 쓴다. 해당 시스템의 원래 값은 같은 버전의 정상 서버에서 확인한다.
ls -l /usr/bin/python3
rpm -qf /usr/bin/python3
패키지 소유가 아닌 직접 만든 링크라면 지우고 되살린다.
sudo rm -f /usr/bin/python3
sudo ln -s /usr/bin/python3.9 /usr/bin/python3 # 실제 버전에 맞춘다
alternatives 로 관리되는 경우도 있다.
sudo alternatives --list | grep -i python
sudo alternatives --config python3
같은 버전의 정상 서버나 설치 미디어에서 RPM 을 가져온다.
# 정상 서버에서
sudo dnf download --resolve --destdir /tmp/fix python3-dnf dnf dnf-data python3-libdnf python3-hawkey
설치 ISO 가 있다면 거기서 꺼내도 된다.
sudo mount -o loop,ro /srv/iso/rhel-9.8-x86_64-dvd.iso /mnt/iso
find /mnt/iso -name 'python3-dnf-*.rpm' -o -name 'dnf-*.rpm'
문제 서버에서 강제로 덮어쓴다.
cd /tmp/fix
sudo rpm -Uvh --replacepkgs --replacefiles ./*.rpm
dnf --version
버전을 정확히 맞춘다. 다른 마이너 버전의 RPM 을 섞으면 의존성이 더 꼬인다. cat /etc/redhat-release 로 확인하고 같은 버전 저장소에서 받는다.
복구 전까지 rpm 은 파이썬과 무관하게 동작하므로 이것으로 패키지를 설치·조회할 수 있다.
rpm -qa | grep dnf
sudo rpm -ivh package.rpm
시스템 파이썬을 건드리지 않는다. 응용 프로그램이 다른 파이썬 버전을 요구하면 /usr/local 이나 별도 경로에 설치하고 venv 또는 pyenv 로 격리한다. sudo pip install 은 쓰지 않는다.
# 시스템과 분리
python3 -m venv /opt/app/venv
/opt/app/venv/bin/pip install -r requirements.txt