Update ManagerやSynaptic Package Managerなどの多くのソフトウェアを見てきましたが、他のプログラムがを使用して/var/lib/dpkg/lock
ロックされている場合は待機します。ターミナルを使用してこれを行うにはどうすればよいですか?apt-get
のマニュアルを見ましたが、有用なものが見つかりませんでした。
sudo apt-get install packagename1 packagename2 packagename3
?
Update ManagerやSynaptic Package Managerなどの多くのソフトウェアを見てきましたが、他のプログラムがを使用して/var/lib/dpkg/lock
ロックされている場合は待機します。ターミナルを使用してこれを行うにはどうすればよいですか?apt-get
のマニュアルを見ましたが、有用なものが見つかりませんでした。
sudo apt-get install packagename1 packagename2 packagename3
?
回答:
このコマンドを使用して、aptdcon
apt-getを直接使用する代わりにaptdaemonと通信することにより、パッケージマネージャータスクをキューに入れることができます。
したがって、基本的にはsudo aptdcon --install chromium-browser
何でもできますし、そのコマンドの実行中に再度実行できますが、異なるパッケージをインストールすると、apt-daemonはエラーを出さずにキューに入れます。
これは、長時間のアップグレードなどを行っているときにパッケージのインストールを継続したい場合、または何かを一緒にスクリプト化し、インストールの信頼性を高めたい場合に特に便利です。
aptdcon
プロンプトを受け入れるように実行できますapt-get -y
か?
yes | aptdcon --hide-terminal --install "package"
ターミナルを非表示にする必要yes
があります。そうしないと、配管によって問題が発生します。
aptdcon
です。私は、VPSの初期設定を行うブートストラップスクリプトに取り組んでいます。VPSでは、バックグラウンドプロセスもいくつかの初期設定を行っています。aptdcon
ロックを回避できるようになるまでインストールできません。
aptdcon
入っていますか?
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/bin
userまたはrootのディレクトリの前に配置されるためですPATH
。
apt
ブート時にいくつかの処理を行うため、dpkg
dpkg dbがロックされているためコマンドが失敗しました。私はcloudinitユーザーデータにこの1行を入れましたwhile fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 1; done; dpkg -i package.deb
。
明らかなこととは別に&&
、あなたは探して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-get
のupgrade
/ dist-upgrade
とaptitude
のsafe-upgrade
/ full-upgrade
。これらはパラメーターを必要としません。aptd
。何と重複するオプションがありapt-key
、apt-cache
、dpkg
行うは。apt-get
それ自体は(aptの他のインスタンスを待つために)そのようなメソッドをサポートしていません。そのためaptdcon
、GUIのパッケージマネージャーに対する推奨ソリューションは次のとおりです。USCはaptd
Synapticと同じバックエンドとして使用します。他の解決策はpackagekit
ですが、探している機能をまだサポートしていません。
aptdcon --install /path/to/pgk.deb
のようdpkg -i
に機能しますが、マニュアルで明示的に言及されているものは見つかりませんでした。
非常に単純なアプローチは、ロックが開かれないのを待つスクリプトです。それ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
、すべての操作についてはいと仮定しますか?
-y
はありませんが望ましいです。
sudo fuser
の中で[[ $(...) ]]
。ファイルがアクセスされると、ゼロの終了コードが返されるので、それで十分です。
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
ポーリング手法を使用できます:
$ time (while ps -opid= -C apt-get > /dev/null; do sleep 1; done); \
apt-get -y install some-other-package
inotify
これを行うスクリプトを作成しました。
#!/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-get
。apt-get
その後、別のインスタンスが既に実行されている場合は待機します。
または、/usr/local/sbin/apt-wait
使用例として保存します。
apt-wait && aptitude
aptitude
ロックを保持している現在のプロセスが終了した後に実行されます。
実行例:
最初に、
apt-get
コマンドが実行されます。次に例を示します。$ sudo apt-get remove some_package
次に、別の端末で別のコマンドが実行されます。
$ sudo apt-get install some_other_package
最初のコマンドが完了するのを待ってから実行します。待機中の出力:
[/] Waiting for other package managers to finish... 28223 : /usr/bin/apt-get remove some_package
inotify
残念ながら、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フラグです。
fuser
、多くの回答に示されているように使用するよりも優れたオプションです。fuser
ロックを監視し、ターゲットプロセスが再びロックを取得する間の競合状態が依然として発生しやすいためです。でflock
ロックを取得し、それはその間にロックを失うための時間を残さないように、ターゲットプロセスに渡されます。
sudo apt-get install packagename && sudo apt-get update
、彼らはお互いの後に自動的に起こります。