web-dev-qa-db-ja.com

Ubuntuクラウドで「apt-daily.service」を無効にする方法VM image?

Ubuntu 16.04サーバーVMイメージは、12時間ごとに「apt-daily.service」を開始するようです。このサービスは、利用可能なパッケージのリストの更新、無人アップグレードの実行など、APT関連のさまざまなタスクを実行します必要な場合など.

VM "snapshot"から開始すると、サービスがトリガーされますすぐにタイマーはずっと前にオフになっているはずです。

ただし、実行中のAPTは、他のaptプロセスが_/var/lib/dpkg_をロックしているため、実行されないようにします。これを示すエラーメッセージは次のようになります。

_E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
_

この自動化されたAPTタスクを無効にする必要があります。これは、Ansibleがマシンのセットアップ(通常はパッケージのインストールを含む)を完了するまでです)を参照してください https://github.com/gc3-uzh-ch/elasticluster/issues/304 詳細とコンテキスト。

_cloud-init_の「ユーザーデータ」スクリプトを使用して「無人アップグレード」機能を無効にするさまざまなオプションを試しましたが、これまでのところすべて失敗しています。

1. systemdタスクを無効にします

systemdタスク_apt-daily.service_は_apt-daily.timer_によってトリガーされます。次のコマンドをさまざまに組み合わせて、どちらか一方または両方を無効にしようとしました。それでも、_apt-daily.service_は、VMがSSH接続を受け入れる準備ができてからすぐに開始されます。

_    #!/bin/bash

    systemctl stop apt-daily.timer
    systemctl disable apt-daily.timer
    systemctl mask apt-daily.service
    systemctl daemon-reload
_

2.構成オプションを無効にする_APT::Periodic::Enable_

スクリプト_/usr/lib/apt/apt.systemd.daily_はいくつかのAPT構成変数を読み取ります;設定_APT::Periodic::Enable_は機能を完全に無効にします(331--337行目)。次のスクリプトで無効にしてみました::

_    #!/bin/bash

    # cannot use /etc/apt/apt.conf.d/10periodic as suggested in
    # /usr/lib/apt/apt.systemd.daily, as Ubuntu distributes the
    # unattended upgrades stuff with priority 20 and 50 ...
    # so override everything with a 99xxx file
    cat > /etc/apt/apt.conf.d/99elasticluster <<__EOF
    APT::Periodic::Enable "0";
    // undo what's in 20auto-upgrade
    APT::Periodic::Update-Package-Lists "0";
    APT::Periodic::Unattended-Upgrade "0";
    __EOF
_

ただし、_APT::Periodic::Enable_の値がコマンドラインから_0_であっても(下記を参照)、_unattended-upgrades_プログラムは引き続き実行されます...

_    ubuntu@test:~$ apt-config Shell AutoAptEnable APT::Periodic::Enable
    AutoAptEnable='0'
_

3. _/usr/lib/apt/apt.systemd.daily_を完全に削除します

次の_cloud-init_スクリプトは、無人アップグレードスクリプトを完全に削除します。

_    #!/bin/bash

    mv /usr/lib/apt/apt.systemd.daily /usr/lib/apt/apt.systemd.daily.DISABLED
_

それでも、タスクは実行され、プロセステーブルで確認できます。コマンドラインからプローブした場合、ファイルは存在しませんが::

_ubuntu@test:~$ ls /usr/lib/apt/apt.systemd.daily
ls: cannot access '/usr/lib/apt/apt.systemd.daily': No such file or directory
_

_cloud-init_スクリプト(SSHコマンドラインと共に)とルートsystemdプロセスが別々のファイルシステムとプロセススペースで実行されているように見えます...

ご質問

私が見逃している明らかな何かがありますか?または、私が気付いていない名前空間の魔法が起こっていますか?

最も重要なこと:_apt-daily.service_スクリプトを使用して_cloud-init_を無効にするにはどうすればよいですか?

70
Riccardo Murri

はい、私が行方不明であることは明らかでした。

Systemdはすべてのサービスの同時開始に関するものなので、cloud-initスクリプトが実行されます同時にapt-daily.serviceがトリガーされます。 cloud-initがユーザー指定のペイロードを実行できるようになるまでに、apt-get updateはすでに実行されています。したがって、2。と3.の試みは、名前空間の魔法が原因で失敗したのではなく、apt.systemd.dailyがシステムに変更を反映させるには遅すぎるために失敗しました。

これはまた、基本的にpreventingapt.systemd.dailyを実行する方法がないことを意味します-開始した後でのみ強制終了できます。

この「ユーザーデータ」スクリプトは次のルートをたどります。

#!/bin/bash

systemctl stop apt-daily.service
systemctl kill --kill-who=all apt-daily.service

# wait until `apt-get updated` has been killed
while ! (systemctl list-units --all apt-daily.service | egrep -q '(dead|failed)')
do
  sleep 1;
done

# now proceed with own APT tasks
apt install -y python

SSHログインが可能な時間帯はまだありますが、apt-getは実行されませんが、ストックのUbuntu 16.04クラウドイメージで動作する別のソリューションは想像できません。

43
Riccardo Murri

注:残念ながら、以下のソリューションの一部はUbuntu 16.04システム(質問者のシステムなど)では機能しません。推奨されるsystemd-run呼び出しはUbuntu 18.04以降でのみ機能します(詳細は コメント を参照)。使用しているUbuntuのバージョンに関係なく、この質問は依然として人気があるので、ここでは答えを残しておきます...

Ubuntu 18.04以降では、起動時のaptの更新/アップグレードに関連するサービスが2つまで存在する場合があります。最初 apt-daily.serviceパッケージのリストを更新します。ただし、2番目のapt-daily-upgrade.serviceこれは、実際にセキュリティ上重要なパッケージをインストールします。 「コマンドが戻る前に無人アップグレードを終了して無効化/削除する」への回答 の質問は、これらの両方が完了するまで待機する方法の優れた例を示しています(便宜上ここにコピーします)。

systemd-run --property="After=apt-daily.service apt-daily-upgrade.service" --wait /bin/true

(これはrootとして実行する必要があることに注意してください)。今後の起動時にこれらのサービスを無効にする場合は、両方のサービスをマスクする必要があります。

systemctl mask apt-daily.service apt-daily-upgrade.service

または、systemctl disable両方のサービスとそれに関連するタイマー(つまりapt-daily.timerおよびapt-daily-upgrade.timer)。

この回答のマスキング/無効化手法は、将来のブートでの更新/アップグレードを防止するだけであることに注意してください。現在のブートですでに実行されている場合、それらは停止しません。

17
Anon

これを無効にするには、「bootcmd」cloud-initモジュールを使用します。これは、ネットワークが立ち上がる前に実行されます。これは、apt updateが実行される前に必要です。

#cloud-config
bootcmd:
    - echo 'APT::Periodic::Enable "0";' > /etc/apt/apt.conf.d/10cloudinit-disable
    - apt-get -y purge update-notifier-common ubuntu-release-upgrader-core landscape-common unattended-upgrades
    - echo "Removed APT and Ubuntu 18.04 garbage early" | systemd-cat

インスタンスにsshしたら、apt-sources/listsを移動するため、cloud-initの最終フェーズが完了するまで待つ必要があります。

# Wait for cloud-init to finish moving apt sources.list around... 
# a good source of random failures
# Note this is NOT a replacement for also disabling apt updates via bootcmd
while [ ! -f /var/lib/cloud/instance/boot-finished ]; do
    echo 'Waiting for cloud-init to finish...'
    sleep 3
done

これは、bootcmdの実行がどの程度早いかを確認するのにも役立ちます。

# Show microseconds in systemd journal
journalctl -r -o short-precise

これは次のように機能することを確認できます。

apt-config dump | grep Periodic

# Verify nothing was updated until we run apt update ourselves.
cd /var/lib/apt/lists
Sudo du -sh .   # small size
ls -ltr         # old timestamps
5
Karl Pickett

ユニットをマスクする方が簡単ではないでしょうか

systemctl mask apt-daily.service

2
user192526

Anonのソリューションに基づいて、このスクリプトを作成しました。このスクリプトを実行してから再起動すると、問題が解決します。

#!/bin/sh

systemctl mask apt-daily.service apt-daily-upgrade.service
systemctl disable apt-daily.service apt-daily-upgrade.service
systemctl disable apt-daily.timer apt-daily-upgrade.timer
1
nemesisfixx

目的がロックエラーを発生させずにマシンをプロビジョニングすることである場合、最も簡単で最も安定した解決策は、apt-dailyロックファイルをロックしながらプロビジョニングツールのリモートコマンド(またはapt関連のコマンド)を実行することです。サービスのマスキング/無効化/待機などはありません。

Ubuntuサーバーでは、パッケージ更新プログラム(apt-daily、unattended-upgrades、cloud-init)がapt-dailyを実行するため、ソリューションを中心にすることができます。

Apt-dailyはflock(2)ロックを使用します。これは、dpkg/apt(fnctlを使用)とは異なり、ロックでの待機をサポートするという便利さを備えたコマンドラインツールで管理できます。

したがって、たとえばChefを使用する場合、ノードで実行するのと同じくらい簡単です。

$ Sudo flock /var/lib/apt/daily_lock chef-client

そして:

  • どちらのchef-clientも最初にロックを取得し、apt-dailyベースのサービスは待機します。
  • または、apt-dailyベースのサービスが最初にそれをロックし、次にchef-clienが待機し、apt-dailyが完了すると最後に実行されます。

ノードでプロビジョナーが呼び出されない場合は、プロビジョナー構成(Ansibleプレイブックなど)を変更して実行できます。

$ Sudo flock /var/lib/apt/daily_lock apt update
$ Sudo flock /var/lib/apt/daily_lock apt upgrade

(またはsh -c '...'などのバリエーション)

ソース: https://saveriomiroddi.github.io/Handling-the-apt-lock-on-ubuntu-server-installations

1
Marcus

これは、whileループで1秒待機し、ロックが解放されているかどうかを確認します。

while : ; do
                sleep 1
                echo $( ps aux | grep -c lock_is_held ) processes are using apt.
                ps aux | grep -i apt
                [[ $( ps aux | grep -c lock_is_held ) > 2 ]] || break
        done
        echo Apt released
1
Navidzj

このcloud-initは機能します。

#cloud-config
apt:
  conf: |
    APT {
      Periodic {
        Update-Package-Lists "0";
      };
    };
    Unattended-Upgrade {
      Package-Blacklist {
        "*";
      };
    };
runcmd:
  - [ systemctl, stop, apt-daily.timer, apt-daily-upgrade.timer ]
  - [ systemctl, disable, apt-daily.timer, apt-daily-upgrade.timer ]

0
Alexander