Надійно перевірте, встановлений чи ні пакет


20

У мене проста вимога. Я хочу визначити кілька змінних, які відповідатимуть будь-якій кількості заданих пакетів, які я хочу встановити за допомогою сценарію оболонки.

Приклад коду нижче:

MISC="shutter pidgin"
WEB="apache2 mongodb"

for pkg in $MISC $WEB; do
    if [ "dpkg-query -W $pkg | awk {'print $1'} = """ ]; then
        echo -e "$pkg is already installed"
    else
        apt-get -qq install $pkg
        echo "Successfully installed $pkg"
    fi
done

Все начебто працює, але логіка здається хибною, оскільки це не надійно встановити потрібні мені пакунки. Він або говорить, що вони вже встановлені, або він намагається встановити пакети, які вже були встановлені раніше.

Я також намагався з command -vчи наступним:

if [ "dpkg -l | awk {'print $2'} | grep --regexp=^$pkg$ != """ ]; then

І навіть за допомогою -nі -zпрапорів, щоб перевірити, чи повернута рядок порожня. Цілком впевнений, що мені тут не вистачає хорошого сенсу.

Чи маєте ви якесь уявлення, що я міг би зробити, щоб переконатися, що пакет фактично встановлений чи ні?

Спасибі!


Яка шкода, якщо ви також зателефонуєте apt-get installна встановлені пакети? Ви могли просто зателефонувати apt-get install $MISC $WEB.
jarno

Відповіді:


15

По суті, вам потрібно лише замінити ifумову

if dpkg --get-selections | grep -q "^$pkg[[:space:]]*install$" >/dev/null; then

Використовувати dpkg-queryйого неможливо , оскільки він повертає справжнє також для видалених, але не очищених пакетів.

Також я пропоную перевірити вихідний код, apt-getперш ніж надсилати успішне повідомлення:

if apt-get -qq install $pkg; then
    echo "Successfully installed $pkg"
else
    echo "Error installing $pkg"
fi

Що робить &>?
Таймон

@Taymon: перенаправляємо і stdin, і stderr на даний файл ( /dev/nullв даному випадку), тому що нам не потрібен вихід, а лише вихідний код. Він працює лише в bash(перший рядок сценарію повинен бути #!/bin/bash) в іншому випадку >/dev/null 2>&1.
enzotib

@Taymon: Я змінив логіку, тому що знайшов недолік у попередньому рішенні.
enzotib

Остерігайтеся: якщо використовується bash і встановлено варіант pipefail, то grep -q може генерувати Heisenbugs. В основному, grep виходить, перш ніж dpkg закінчить запис (у такому випадку потрібно статус виходу 0), тому dpkg не вдасться записати на трубу (що натомість генерує статус виходу не 0). Або переконайтесь, що pipefail не встановлено, або відмовтесь від (можливо, крихітних) підвищення ефективності опції "-q".
Рон Берк

2

Ви можете перевірити його за допомогою dpkg-запиту:

if dpkg-query -W -f'${Status}' "$pkg" 2>/dev/null | grep -q "ok installed"; then

Зауважте, що * і? є символами, якщо вони відображаються у $ pkg. Я думаю, що dpkg-запит може надрукувати "встановлено знову необхідне встановлення" замість "встановлено", якщо пакет зламаний і його потрібно перевстановити командою, apt-get install --reinstallяка також може бути використана для встановлення нових пакетів.


0
#to check package is installed or not without distribution dependency
#!/bin/bash
read -p "Package Name: " pkg
which $pkg > /dev/null 2>&1
if [ $? == 0 ]
then
echo "$pkg is already installed. "
else
read -p "$pkg is not installed. Answer yes/no if want installation_ " request
if  [ $request == "yes" ]
then
yum install $pkg
fi
fi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.