시스템 패키지 관리자 식별

시스템 패키지 관리자 식별

기본 시스템 패키지 관리자를 식별하는 방법(스크립트에서)이 있습니까?

명확히 하자면, 제가 하고 싶은 것은 주어진 명령을 실행하는 것입니다. Debian이나 그 파생물에서는 "apt"와 같은 것을 반환하고, openSUSE에서는 "zypp"를 반환하고, Fedora 등에서는 "yum"을 반환합니다. Arch Linux는 "pacman" 등을 반환합니다.

아래 방법으로 이 작업을 수행할 수 있다는 것을 알고 있습니다. 동일한 이름을 가진 실행 파일이 있는 한 중단되지 않는 더 강력한 방법이 있는지 궁금합니다.

which apt >/dev/null 2>&1
if [ $? -eq 0 ]
then
    echo "apt"
fi
# etc...

답변1

바이너리가 아닌 배포판을 식별하는 것부터 시작해야 합니다.

다음은 bash 스크립트에서 작동하는 몇 줄의 코드입니다.

declare -A osInfo;
osInfo[/etc/redhat-release]=yum
osInfo[/etc/arch-release]=pacman
osInfo[/etc/gentoo-release]=emerge
osInfo[/etc/SuSE-release]=zypp
osInfo[/etc/debian_version]=apt-get
osInfo[/etc/alpine-release]=apk

for f in ${!osInfo[@]}
do
    if [[ -f $f ]];then
        echo Package manager: ${osInfo[$f]}
    fi
done

이러한 파일이 수정되어 이 방법이 실패할 수 있지만 이는 매우 비표준 구성이므로 대부분의 경우 작동합니다.

답변2

다음 질문에 대해 허용되는 답변부터 시작하세요.간단한 쉘 스크립트에서 배포 이름과 버전 번호를 어떻게 얻을 수 있습니까?. 그런 다음 감지된 배포판에 따라 사용할 패키지 관리자를 결정합니다.

답변3

다른 경로를 검토한 후 이 경로를 선택했습니다. 이는 많은 Docker 컨테이너를 실행 중이고 컬/jq가 필요하며 작업 간에 사용 가능한 항목에 의존할 수 없을 때 발생합니다.

script:
 - packagesNeeded='curl jq'
 - if [ -x "$(command -v apk)" ];       then sudo apk add --no-cache $packagesNeeded
 - elif [ -x "$(command -v apt-get)" ]; then sudo apt-get install $packagesNeeded
 - elif [ -x "$(command -v dnf)" ];     then sudo dnf install $packagesNeeded
 - elif [ -x "$(command -v zypper)" ];  then sudo zypper install $packagesNeeded
 - else echo "FAILED TO INSTALL PACKAGE: Package manager not found. You must manually install: $packagesNeeded">&2; fi

순수 bash에서는:

packagesNeeded=(curl jq)
if [ -x "$(command -v apk)" ];
then
    sudo apk add --no-cache "${packagesNeeded[@]}"
elif [ -x "$(command -v apt-get)" ];
then
    sudo apt-get install "${packagesNeeded[@]}"
elif [ -x "$(command -v dnf)" ];
then
    sudo dnf install "${packagesNeeded[@]}"
elif [ -x "$(command -v zypper)" ];
then
    sudo zypper install "${packagesNeeded[@]}"
else
    echo "FAILED TO INSTALL PACKAGE: Package manager not found. You must manually install: "${packagesNeeded[@]}"">&2;
fi

command -v종료 상태를 직접 테스트할 수도 있습니다.

if command -v apk &> /dev/null
then
    sudo apk add ...
fi

답변4

저는 여기에서 몇 가지 아이디어를 빌렸고, 출시를 위해 다른 곳에서도 몇 가지 아이디어를 빌렸습니다. 저는 이것을 컨테이너 이미지 빌드의 일부로 사용합니다. 먼저 기본 이미지의 배포를 알 필요 없이 "범용" 설치를 수행하겠습니다. 물론 패키지 이름이 배포판마다 다르면 패키지 이름은 그대로 실패합니다.

#!/bin/bash
pkg_install () {

local distro;local cmd;local usesudo
declare -A pkgmgr
pkgmgr=( \
[arch]="pacman -S --noconfirm" \
[alpine]="apk add --no-cache" \
[debian]="apt-get install -y" \
[ubuntu]="apt-get install -y" \
)

distro=$(cat /etc/os-release | tr [:upper:] [:lower:] | grep -Poi '(debian|ubuntu|red hat|centos|arch|alpine)' | uniq)
cmd="${pkgmgr[$distro]}"
[[ ! $cmd ]] && return 1
if [[ $1 ]]; then
[[ ! $EUID -eq 0 ]] && usesudo=sudo 
echo installing packages command: $usesudo $cmd $@
$usesudo $cmd $@
else 
echo $cmd
fi
}

# if script was executed then call the function
(return 0 2>/dev/null) || pkg_install "$@"

직접 실행하거나 가져와서 함수를 호출할 수 있습니다. 저는 centos나 redhat을 사용하지 않지만 해당 항목을 배열에 추가하거나 지원하지 않는 항목을 제거할 수 있습니다.

나는 posix 버전을 작성해야 했기 때문에(alpine과 같은 일부 기본 이미지에는 기본적으로 bash가 설치되어 있지 않기 때문에) 여기에 있습니다.

#!/bin/sh
hm_hash() {
    echo "$1" | md5sum -
}

hm_put() {
    echo "$3" > "$1/$(hm_hash "$2")"
}

hm_get() {
    cat "$1/$(hm_hash "$2")"
}

pkg_install () {

local distro;local cmd;local usesudo; local pkgmgr
pkgmgr="$(mktemp -d)"
hm_put "$pkgmgr" arch "pacman -S --noconfirm" 
hm_put "$pkgmgr" alpine "apk add --no-cache"
hm_put "$pkgmgr" debian "apt-get install -y"
hm_put "$pkgmgr" ubuntu "apt-get install -y" 

distro=$(cat /etc/os-release | tr [:upper:] [:lower:] | grep -Poi '(debian|ubuntu|red hat|centos|arch|alpine)' | uniq)
cmd=$(hm_get "$pkgmgr" $distro 2> /dev/null)
rm -rf $pkgmgr
if [ ! -z "$cmd" ]; then
    if [ -z "$1" ]; then
    echo $cmd
    else 
    echo installing packages command: $cmd $@
    $cmd $@
    fi
 else  
   return 1  
 fi  
}

# if script was executed then call the function
(return 0 2>/dev/null) || pkg_install "$@"

관련 정보