APTの別のインスタンスが実行されている場合、パッケージマネージャーを待機させる方法は?


50

Update ManagerやSynaptic Package Managerなどの多くのソフトウェアを見てきましたが、他のプログラムがを使用して/var/lib/dpkg/lockロックされている場合は待機します。ターミナルを使用してこれを行うにはどうすればよいですか?apt-getのマニュアルを見ましたが、有用なものが見つかりませんでした。


apt-getコマンドをいくつか実行できます。好きでsudo apt-get install packagename && sudo apt-get update、彼らはお互いの後に自動的に起こります。
アルヴァ

1
これはそれをしません:sudo apt-get install packagename1 packagename2 packagename3
リンツウィンド

unix.stackexchange.com/questions/463498/を参照してください。Ubuntu18.04以降で起動時間の終了を待ちたい特別な場合は)
Anon

回答:


35

このコマンドを使用してaptdconマンページアイコン apt-getを直接使用する代わりにaptdaemonと通信することにより、パッケージマネージャータスクをキューに入れることができます。

したがって、基本的にはsudo aptdcon --install chromium-browser何でもできますし、そのコマンドの実行中に再度実行できますが、異なるパッケージをインストールすると、apt-daemonはエラーを出さずにキューに入れます。

これは、長時間のアップグレードなどを行っているときにパッケージのインストールを継続したい場合、または何かを一緒にスクリプト化し、インストールの信頼性を高めたい場合に特に便利です。


4
aptdconプロンプトを受け入れるように実行できますapt-get -yか?
ノキ

4
yes | aptdcon --hide-terminal --install "package"ターミナルを非表示にする必要yesがあります。そうしないと、配管によって問題が発生します。
whitehat101

1
この答えの問題は、インストールが必要なことaptdconです。私は、VPSの初期設定を行うブートストラップスクリプトに取り組んでいます。VPSでは、バックグラウンドプロセスもいくつかの初期設定を行っています。aptdconロックを回避できるようになるまでインストールできません。
偽の名前

2
おそらくcloud-initを使用する初期サーバー構成の@FakeName
Jorge Castro

1
どのパッケージにaptdcon入っていますか?
ctrl-alt-delor

45

apt-get別のソフトウェアマネージャーが実行されている場合に待機することを学習させることができます。次の画面キャストの動作と似たもの:

ここに画像の説明を入力してください

どうやって作ったの?

ディレクトリ内にapt-get(wrapper for apt-get)という新しいスクリプトを作成/usr/local/sbinし、次のbashコードを内部に入れます。

#!/bin/bash

i=0
tput sc
while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do
    case $(($i % 4)) in
        0 ) j="-" ;;
        1 ) j="\\" ;;
        2 ) j="|" ;;
        3 ) j="/" ;;
    esac
    tput rc
    echo -en "\r[$j] Waiting for other software managers to finish..." 
    sleep 0.5
    ((i=i+1))
done 

/usr/bin/apt-get "$@"

実行可能にすることを忘れないでください:

sudo chmod +x /usr/local/sbin/apt-get

テストする前に、すべてが正常かどうかを確認します。which apt-getコマンドの出力はnowになります/usr/local/sbin/apt-get。その理由は、デフォルトでは、/usr/local/sbinディレクトリは/usr/binuserまたはrootのディレクトリの前に配置されるためですPATH


それは本当に私の質問への直接のヒットです。おかげで:)
rɑːdʒɑ13年

2
スクリプトはapt-getのスタックインスタンスをどのように管理しますか?たとえば、終了する前に5つのapt-getを起動しますか?
Braiam

@Braiam心から、私は知りません。私は良いテスターではありません。テストしましたか?問題が発生した場合、スクリプトの新しいインスタンスが開始するときにタイムスタンプ付きの新しいロックを作成することにより、スクリプトを改善できます(単なる例-他にも多くの方法があります)。
ラドゥラデアヌ

うわー!雄弁。これまで私が投げてきたすべてのもので魅力のように動作します!親指が2つあります...これはパッケージの一部である必要があります:D
Eric

2
それは最高です!AWS cloudinitを使用して新しいサーバーにパッケージをインストールする際に問題が発生しましたが、Ubuntuはaptブート時にいくつかの処理を行うため、dpkgdpkg dbがロックされているためコマンドが失敗しました。私はcloudinitユーザーデータにこの1行を入れましたwhile fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 1; done; dpkg -i package.deb
ボロディミールSmotesko

20

明らかなこととは別に&&、あなたは探してaptdconいるかもしれません。このツールは、aptの他のインスタンスを検出し、終了するまで待機できます。

sudo aptdcon --safe-upgrade
[/] 11%他のソフトウェアマネージャーが終了するのを待っているaptitude 待っている

(私は別の場所でaptitudeを実行しています)

このツールの利点は、次に行うことを心配することなく、複数のアクションを連続してストックできることです。aptdconフロントエンドをブロックしないようにツールをバックグラウンドで実行できるため、無人スクリプトおよびGUIインストールに最適です。

によってサポートさaptdconれる操作は次のとおりです。

  • --refresh-c:これはと同等apt-get updateです。パッケージリストが更新されます。
  • --install--remove--upgrade--purge--downgrade。それらのそれぞれは、彼らの名前が言うように行います。パッケージの名前は必須です。-i-r-u-p:これらは、いずれかを持っていないダウングレードを除くすべてのための短いオプション、です。
  • --safe-upgrade--full-upgradeに対応しているapt-getupgrade/ dist-upgradeaptitudesafe-upgrade/ full-upgrade。これらはパラメーターを必要としません。
  • 他にもいくつかの操作があり、それらはマニュアルに記載されています。ただし、これらはに興味のあるユーザーに最もよく使用されますaptd。何と重複するオプションがありapt-keyapt-cachedpkg行うは。

apt-getそれ自体は(aptの他のインスタンスを待つために)そのようなメソッドをサポートしていません。そのためaptdcon、GUIのパッケージマネージャーに対する推奨ソリューションは次のとおりです。USCはaptdSynapticと同じバックエンドとして使用します。他の解決策はpackagekitですが、探している機能をまだサポートしていません。


1
aptdcon --install /path/to/pgk.debのようdpkg -iに機能しますが、マニュアルで明示的に言及されているものは見つかりませんでした。
whitehat101

パッケージ内のインストール後スクリプトでこれを使用できますか?
ネルソンテイシェイラ

@NelsonTeixeiraはなぜppst-installスクリプトでこれを使用するのですか?ポストインストールが実行されている場合、明らかにaptが実行されています。
ブライアム

リポジトリにない特別なパッケージをpostinstallにインストールさせたいです。これは可能ですか?それらをパッケージに含め、スクリプトはインストールの完了後にインストールします。
ネルソンテイシェイラ

@NelsonTeixeira再び、なぜそれが必要なのでしょうか?ポストインストールスクリプトは、パッケージがインストールされている場合にのみ実行されます。代わりに質問して、ケースをより詳細に説明することをお勧めします。
ブライアム

18

非常に単純なアプローチは、ロックが開かれないのを待つスクリプトです。それwaitforaptを呼び出して貼り付けましょう/usr/local/bin

#!/bin/sh

while sudo fuser /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock >/dev/null 2>&1; do
   sleep 1
done

次に、実行しsudo waitforapt && sudo apt-get install whateverます。例外を追加しsudoersて、パスワードを必要とせずに実行できるようにすることができます(そのapt-getためにパスワードが必要になるので、大きな利益はありません)。

残念ながら、これはキューに入れません。aptの操作の一部が対話的である(「これらのパッケージをすべて削除してもよろしいですか?!」)ことを考えると、これを回避する良い方法が見つかりません...


たぶん-y、すべての操作についてはいと仮定しますか?
ブライアム

ありがとうございました。エイリアスヘルプを使用すると、より適切に使用できると思います。
rɑːdʒɑ

3
確かで-yはありませんが望ましいです。
オリ

1
私はあなたがラップしたくないと思うsudo fuserの中で[[ $(...) ]]。ファイルがアクセスされると、ゼロの終了コードが返されるので、それで十分です。
キリ

4
私はapt-getをして作業する際関与するいくつかのロックがあるので、より完全なものには、以下の解決策を見つけた: while sudo fuser /var/lib/dpkg/lock /var/lib/apt/lists/lock /var/cache/apt/archives/lock >/dev/null 2>&1; do echo 'Waiting for release of dpkg/apt locks'; sleep 5; done; sudo apt-get -yy update
マヌエル・キースリンク

3

ポーリング手法を使用できます:

$ time (while ps -opid= -C apt-get > /dev/null; do sleep 1; done); \
  apt-get -y install some-other-package

良く使用するinotify
Ctrl + Alt + delor

3

これを行うスクリプトを作成しました。

#!/bin/bash

# File path to watch
LOCK_FILE='/var/lib/dpkg/lock'

# tput escape codes
cr="$(tput cr)"
clr_end="$(tput el)"
up_line="$(tput cuu 1)"

CLEAN(){
    # Cleans the last two lines of terminal output,
    # returns the cursor to the start of the first line
    # and exits with the specified value if not False

    echo -n "$cr$clr_end"
    echo
    echo -n "$cr$clr_end$up_line"
    if [[ ! "$1" == "False" ]]; then
        exit $1
    fi
}

_get_cmdline(){
    # Takes the LOCKED variable, expected to be output from `lsof`,
    # then gets the PID and command line from `/proc/$pid/cmdline`.
    #
    # It sets `$open_program` to a user friendly string of the above.

    pid="${LOCKED#p}"
    pid=`echo $pid | sed 's/[\n\r ].*//'`
    cmdline=()
    while IFS= read -d '' -r arg; do
        cmdline+=("$arg")
    done < "/proc/${pid}/cmdline"
    open_program="$pid : ${cmdline[@]}"
}

# Default starting value
i=0

# Checks if the file is locked, writing output to $FUSER
while LOCKED="$(lsof -F p "$LOCK_FILE" 2>/dev/null)" ; do
    # This will be true if it isn't the first run
    if [[ "$i" != 0 ]]; then
        case $(($i % 4)) in
            0 ) s='-'
                i=4
                _get_cmdline # Re-checks the command line each 4th iteration
            ;;
            1 ) s=\\ ;;
            2 ) s='|' ;;
            3 ) s='/' ;;
        esac
    else
        # Traps to clean up the printed text and cursor position
        trap "CLEAN False; trap - SIGINT ; kill -SIGINT $$" SIGINT
        trap 'CLEAN $((128+15))' SIGTERM
        trap 'CLEAN $((128+1))' SIGHUP
        trap 'CLEAN $((128+3))' SIGQUIT

        # Default starting character
        s='-'

        _get_cmdline
        echo -n "$save_cur"
    fi
    # Prints the 2nd line first so the cursor is at the end of the 1st line (looks nicer)
    echo
    echo -n "$cr$clr_end$open_program"
    echo -n "$up_line$res_cur$cr$clr_end[$s] Waiting for other package managers to finish..."
    #echo -en "$cr$clr_end[$s] Waiting for other package managers to finish..."
    #echo -en "\n$cr$clr_end$open_program$cr$up_line"
    ((i++))
    sleep 0.025
done

CLEAN False

# This allows saving the script under a different name (e.g. `apt-wait`)
# and running it. It only imitates `apt-get` if it was launched as such
if [[ "${0##*/}" == 'apt-get' ]]; then
    exec /usr/bin/apt-get "$@"
    exit $?
fi

上記をに保存します/usr/local/sbin/apt-getapt-getその後、別のインスタンスが既に実行されている場合は待機します。

または、/usr/local/sbin/apt-wait使用例として保存します。

apt-wait && aptitude

aptitudeロックを保持している現在のプロセスが終了した後に実行されます。

実行例:

  1. 最初に、apt-getコマンドが実行されます。次に例を示します。

    $ sudo apt-get remove some_package
    
  2. 次に、別の端末で別のコマンドが実行されます。

    $ sudo apt-get install some_other_package
    

    最初のコマンドが完了するのを待ってから実行します。待機中の出力:

    [/] Waiting for other package managers to finish...
          28223 : /usr/bin/apt-get remove some_package
    

1
良く使用するinotify
Ctrl + Alt + delor

3

残念ながら、lxcのような異なる特権のないネームスペースコンテナで実行している場合、fuserはあまり役に立ちません。

また、aptdconはデフォルトではインストールされず(少なくとも18.04では)、タスクをキューにバックグラウンド化するため、シリアル化が失われます。これは乗り越えられないわけではありませんが、aptdconをインストールするときに、自動化でaptの群れエラーを回避する方法が必要であり、aptdconを介してパッケージをインストールした後にシリアル化する必要があるものに対して何らかの待機ループが必要になることを意味します既に何らかのフラグがある場合を除きます。

動作するのは群れです。これはNFSなどでも機能するはずです。aptと同じようにファイルシステムのロックを使用するため、エラーをスローする代わりにロックで待機するのは-w secondsパラメーターのみです。

したがって、ラッパーモデルに従って、これをapt-getとして/ usr / local / bin /に追加し、共有します。

これには、aptで並列処理を許可しないことでIOを制限するという利点もあるため、ディスクを破壊することなく、深夜0時にcronで更新をトリガーできます。

#!/bin/bash
exec /usr/bin/flock -w 900 -F --verbose /var/cache/apt/archives/lock /usr/bin/apt-get $@  

apt-getに対する非常に素晴らしくシンプルな機能要求は、ブロッキング/待機ロックに切り替える-wフラグです。


aptはflockではなくfcntlを使用するため、これは機能しません。askubuntu.com/questions/1077215/...
アンディ・

これは完全に機能しfuser、多くの回答に示されているように使用するよりも優れたオプションです。fuserロックを監視し、ターゲットプロセスが再びロックを取得する間の競合状態が依然として発生しやすいためです。でflockロックを取得し、それはその間にロックを失うための時間を残さないように、ターゲットプロセスに渡されます。
jrudolph

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.