題 測試APT中是否安裝了軟件包


我想要一個shell腳本方法來測試/報告是否安裝了包。我不需要細節,只有布爾返回設置邏輯流程。我在看 查找是否已安裝軟件包但是 dpkg 返回複雜輸出及其格式更改,具體取決於包是在Debian存儲庫中還是在Ubuntu PPA中。

我找到 apt-cache 做得很好,我想出了這個方法:

is_installed=0
test_installed=( `apt-cache policy package-name | grep "Installed:" ` )
[ ! "${test_installed[1]}" == "(none)" ] && is_installed=1

有誰知道更簡單或更直接的方式?


8
2018-05-22 07:26


起源




答案:


dpkg-query 如在您的鏈接帖子中似乎是最正確的工作工具,除了使用例如可用的Python庫在這樣的腳本環境中直接綁定到APT系統。

dpkg-query

dpkg-query -Wf'${db:Status-abbrev}' package-name 2>/dev/null | grep -q '^i'

將返回true(退出狀態 0 在shell腳本中)如果安裝了包,則為false(退出狀態 1) 除此以外。

  • -W 意思是“顯示”(dpkg-query 必須要求採取行動)。
  • -f 更改輸出的格式。
  • db:Status-abbrev 是包狀態的縮寫形式。
  • 2>/dev/null 沉默 dpkg-query 如果給出了無效的包名稱。如何處理這可能是個案問題。
  • grep -q 如果匹配則返回true,否則返回false。

如果它經常使用,它可以成為一個簡單的功能:

#!/bin/sh
debInst() {
    dpkg-query -Wf'${db:Status-abbrev}' "$1" 2>/dev/null | grep -q '^i'
}

if debInst "$1"; then
    printf 'Why yes, the package %s _is_ installed!\n' "$1"
else
    printf 'I regret to inform you that the package %s is not currently installed.\n' "$1"
fi

或者只是簡單地

#!/bin/sh
if dpkg-query -Wf'${db:Status-abbrev}' "$1" 2>/dev/null | grep -q '^i'; then
    printf 'Why yes, the package "%s" _is_ installed!\n' "$1"
else
    printf 'I regret to inform you that the package "%s" is not currently installed.\n' "$1"
fi

11
2018-05-22 08:59



雖然這無疑是正確的,但我發現了這一點 dpkg-query -l "$package" | grep -q ^.i 通常是足夠的(並且更容易記住)。 - phogg
@phogg:是的,取決於它是否應該存在於腳本中。而且, dpkg-query -l 輸出不是一成不變的,因為它只是一個用戶演示模式,所以如果演示文稿發生變化,這樣的劇本可能會破壞。 - Daniel Andersson
@Daniel。我喜歡返回碼方法。請在代碼中查看我的回答。 - tahoar
在10.04格式選項db:Status-abbrev似乎不存在 - 我用過: dpkg-query -Wf'${Version}' ${pkg} 2>/dev/null | grep -q '^\d*' 達到同樣的效果。 - scottynomad


我用以下結果測試了Daniel對三個包的建議:

  1. 未安裝Native Debian存儲庫包:

    ~$ dpkg-query -Wf'${db:Status-abbrev}' apache-perl
    ~$ echo $?
    1
    
  2. PPA包在主機上註冊並安裝:

    ~$ dpkg-query -Wf'${db:Status-abbrev}' libreoffice
    ~$ echo $?
    0
    
  3. PPA包在主機上註冊但未安裝:

    ~$ dpkg-query -Wf'${db:Status-abbrev}' domy-ce
    ~$ echo $?
    0
    ~$ sudo apt-get remove domy-ce
    [sudo] password for user: 
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    Package domy-ce is not installed, so not removed
    0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
    

雖然我喜歡這種方法,但似乎我不相信PPA包的返回代碼。沒錯,我想我會堅持解析回歸 apt-cache policy 命令。


1
2018-05-23 12:56



好吧,你的代碼示例不是我說你應該做的,但我猜你剛剛錯過了 grep 參與你的粘貼。我無法真正重現您的問題,但這可能是因為代碼示例目前尚未完成,因此請修復此問題。你運行Debian或Ubuntu嗎? - Daniel Andersson
我正在運行Ubuntu 10.04(PPA支持沒有直接的Debian?)。我的代碼刪除了你的grep,因為1)dkpg-query命令沒有向stdout寫入任何東西,grep總是拋出一個返回碼。如果安裝,dpkg-query返回碼為0。 - tahoar
1.不要標記你的帖子“Debian”。我認為你不理解這一部分 grep 在命令中播放,所以你剝離它,現在你說它不起作用? grep -q 給出返回碼 1 如果它 不 匹配,即程序是 不 安裝或不可用,或 0 如果程序已安裝。我在帖子中解釋過。 - Daniel Andersson


#!/bin/bash

# Check for dependencies 
check_deps () {
DEPS=$(echo {dialog,sqlite3,openssh-client})
for i in $DEPS ; do
    dpkg-query -W -f='${Package}\n' | grep ^$i$ > /dev/null
    if [ $? != 0 ] ; then
        echo "Installing deps ..."
        aptitude install $i -y > /dev/null
    fi
done  
}

# execute the check_deps function
check_deps

1
2018-02-11 16:06



-1,問題不在於依賴性檢查。另外,解釋命令的各個部分正在做什麼:否則其他人無法看到正在發生的事情。 - Daniel Andersson
DEPS=$(echo {dialog,sqlite3,openssh-client}) 可以等同地寫成 DEPS="dialog sqlite3 openssh-client"。 - Daniel Andersson


我喜歡Daniel Andersson的答案,但它對我不起作用。我在Ubuntu 12.04上。

來自 dpkg手冊頁db:Status-abbrev 僅適用於dpkg 1.16.2+:

          db:Status-Abbrev
                 It  contains the abbreviated package status, such as “ii”
                 (since dpkg 1.16.2).

我的解決方案是使用遺留行為,只是 Status 格式:

dpkg-query -Wf'${Status}' {my_pkg_name}

輸出

install ok installed 

我猜這是其他表現形式中“ii”的靈感來源。

因此,要完全適應Daniel Andersson對舊版dpkg工作的回答,以及較舊的Ubuntu發行版:

dpkg-query -Wf'${Status}' {your_pkg_name} 2>/dev/null | grep -q "install ok installed"

返回:

  • 0 - 安裝包,或
  • 1 - 未安裝包。

1
2018-05-10 20:48