Kiểm tra đáng tin cậy nếu một gói được cài đặt hay không


20

Tôi có một yêu cầu đơn giản. Tôi muốn xác định một số biến sẽ tương ứng với bất kỳ số lượng gói nhất định nào tôi muốn cài đặt thông qua tập lệnh shell.

Mã mẫu dưới đây:

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

Mọi thứ đều hoạt động, nhưng logic có vẻ không hoàn hảo vì nó không đáng tin cậy để cài đặt các gói tôi muốn. Nó cũng nói rằng họ đã được cài đặt hoặc đang cố cài đặt các gói đã được cài đặt trước đó.

Tôi cũng đã từng thử command -vhoặc sau:

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

Và thậm chí với các cờ -n-zđể kiểm tra xem chuỗi trả về có trống không. Khá chắc chắn rằng tôi đang thiếu một số ý nghĩa tốt ở đây.

Bạn có biết tôi có thể làm gì để đảm bảo một gói thực sự được cài đặt hay không?

Cảm ơn!


Điều gì có hại, nếu bạn gọi apt-get installcho các gói cài đặt, quá? Bạn chỉ có thể gọi apt-get install $MISC $WEB.
jarno

Câu trả lời:


15

Về cơ bản bạn chỉ cần thay thế ifđiều kiện bằng

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

Không thể sử dụng dpkg-query, vì nó trả về true cũng cho các gói bị xóa nhưng không bị xóa.

Ngoài ra tôi đề nghị kiểm tra mã thoát của apt-gettrước khi đưa ra thông báo thành công:

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

Không gì &>làm gì?
Taymon

@Taymon: chuyển hướng cả stdin và stderr đến tệp đã cho ( /dev/nulltrong trường hợp này), vì chúng tôi không cần đầu ra, chỉ có mã thoát. Nó chỉ hoạt động trong bash(dòng đầu tiên của tập lệnh phải có #!/bin/bash) nếu không sử dụng >/dev/null 2>&1.
enzotib

@Taymon: Tôi đã thay đổi logic, vì tôi đã tìm thấy một lỗ hổng trong giải pháp trước đó.
enzotib

Chú ý: nếu sử dụng bash và tùy chọn pipefail được đặt, thì grep -q có thể tạo Heisenbugs. Về cơ bản, grep thoát trước khi dpkg kết thúc việc viết (bạn muốn có trạng thái thoát 0 trong trường hợp đó) vì vậy dpkg không ghi vào đường ống (thay vào đó tạo ra trạng thái thoát không 0). Hãy chắc chắn rằng đường ống không được đặt hoặc từ bỏ mức tăng hiệu quả (có thể là nhỏ) của tùy chọn "-q".
Ron Burk

2

Bạn có thể kiểm tra nó bằng dpkg-query:

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

Lưu ý rằng * và? là các ký tự đại diện, nếu chúng xuất hiện bằng $ pkg. Tôi đoán dpkg-query có thể in "cài đặt lại yêu cầu" thay vì "cài đặt ok", nếu gói bị hỏng và cần được cài đặt lại bằng lệnh apt-get install --reinstallcó thể được sử dụng để cài đặt các gói mới.


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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.