デフォルトのシステムパッケージマネージャを識別する方法(スクリプトから)はありますか?
明確にすると、私がやりたいことは与えられたコマンドを実行することです。 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コンテナを実行しており、curl / 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 "$@"