古いカーネルのみを削除するBash one-liner


23

/ bootパーティションの領域を解放する方法について多くのスレッドを見てきましたが、それも私の目標です。しかし、私は古いカーネルを削除することだけに興味があり、カーネルのそれぞれではなく現在のものを削除します。

Puppetからスクリプトを実行し、余分なファイルを置きたくないので、このソリューションがワンライナーである必要があります。これまでのところ、私は次のものを得ました:

dpkg -l linux-* | awk '/^ii/{print $2}' | egrep [0-9] | sort -t- -k3,4 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"` | xargs sudo apt-get -y purge

より正確に言うと、現時点で行われていることは次のとおりです。

  • すべてのlinux- *パッケージをリストし、名前を出力します。
  • 数字のあるものだけをリストし、それらをソートして、逆の結果を返します。この方法では、古いカーネルが最後にリストされます。
  • 現在のカーネルより後の結果のみを出力します
  • linux- {image、headers}の結果がいくつかあるため、現在のカーネルに関連するものをパージしないようにしてください。
  • パージするためにaptを呼び出す

これは機能しますが、少なくとも20台のサーバーがUbuntuを実行しているため、ソリューションはより洗練され、運用環境にとって安全であると確信しています。

お時間をありがとう、アレハンドロ。


ネットから古いもの:tuxtweaks.com/2010/10/…– user68186 14
1

スクリプトファイルに保存されていない場合、ワンライナーをどのように使用しますか?
ジャーノ

回答:


25

ほんの少しのコメントで十分に見えます。最初の2つのコメントはコマンドをより安全にし、3番目と4番目のコメントはコマンドを少し短くします。それらのいずれかを自由にフォローまたは無視してください。最初の2つに従うことを強くお勧めしますが。あなたはそれが可能な限り安全であることを確認したい。私は真剣に意味します。sudo apt-get -y purge自動的に生成されたパッケージリストを投げています。それはとてもです!:)

  1. すべてlinux-*をリストすると、(私の出力の例)のような多くの誤検知が得られますlinux-sound-base。これらはコマンドの残りの部分によって後で除外される可能性がありますが、そもそもリストに入れない方が安全だと思います。削除するパッケージをより適切に制御します。予期しない結果が生じる可能性のあることをしないでください。だから私はで始めます

    dpkg -l linux-{image,headers}-*
  2. 「数字のあるものだけをリストする」という正規表現は、私の意見では少し単純すぎます。たとえばlinux-libc-dev:amd64、64ビットシステムを使用している場合にパッケージがあります。正規表現が一致します。一致させたくない。確かに、あなたが私の最初のアドバイスに従えば、linux-libc-dev:amd64とにかくリストされませんが、それでもです。バージョン番号の構造については、「番号があります」という単純な事実よりも多くのことを知っています。さらに、シェルによる潜在的な誤解を防ぐためだけに、正規表現を引用することは一般に良い考えです。だから私はそのegrepコマンドを作成します

     egrep '[0-9]+\.[0-9]+\.[0-9]+'
  3. 次に、このソート処理があります。なぜソートするのですか?とにかくすべてのカーネル(現在のカーネルを除く)を削除するので、古いカーネルを新しいカーネルより先に削除することが重要ですか?違いはないと思います。それともsed、「現在のカーネルの後にある結果のみを印刷する」ために使用できるようにするだけですか?しかし、IMOは非常に複雑に感じます。grep -vとにかくすでにやっているように、あなたの現在のカーネルに対応する結果を単純に除外しないのはなぜですか?正直なところ、あなたのコマンドの最初の部分を取り込んだ場合(以前の2つの提案が統合されている)、私のマシンで

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | sort -t- -k3,4 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"`
    linux-image-3.8.0-34-generic
    linux-image-3.5.0-44-generic

    そのソート/セッドのものを削除すると、私は得る

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v -e `uname -r | cut -f1,2 -d"-"`
    linux-image-3.5.0-44-generic
    linux-image-3.8.0-34-generic
    linux-image-extra-3.5.0-44-generic
    linux-image-extra-3.8.0-34-generic

    したがって、あなたのより複雑なコマンドは実際に私のマシン上の2つのパッケージを見逃します、私は削除したいと思います(今ではそれらのlinux-image-extra-*モノがモノに依存しているlinux-image-*ので、とにかく削除される可能性がありますが、それを明示するために傷つけることはできません)。とにかく、あなたのソートのポイントはわかりません。grep -v派手な前処理を行わないシンプルなもので十分で、おそらくさらに良いでしょう。私はKISSの原則を支持しています。後で理解したりデバッグしたりしやすくなります。また、並べ替えをせずにわずかに効率的です;)

  4. これは純粋に審美的ですが、このわずかに短いバリアントでも同じ出力が得られます。:-)

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v $(uname -r | cut -d- -f-2)
    linux-image-3.5.0-44-generic
    linux-image-3.8.0-34-generic
    linux-image-extra-3.5.0-44-generic
    linux-image-extra-3.8.0-34-generic

その結果、よりシンプルで安全なコマンドになります

$ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | grep -v $(uname -r | cut -d- -f-2) | xargs sudo apt-get -y purge

あなたが実際にあなたのクリーンアップするので/boot、パーティションを、完全に異なるアプローチがの内容一覧表示することであろう/boot使用をdpkg -S、個々のファイルが属するパッケージを決定するために、現在のカーネルに属するものを除外し、そして得られたパッケージを削除します。しかし、私、それはまたのような時代遅れのパッケージを見つけるになるので、より良いあなたのアプローチのようlinux-headers-*にインストールされません。これは、/bootこれだけにし、/usr/src


返信@Malteに感謝します。ご意見ありがとうございます。最初の2つのステップが非常に明確になり、ワンライナーがより安全になりました。ただし、最後の2つの手順では、新しいカーネルを無視し、同様にパージします。少なくとも、私のサーバーでソリューションを試したところ、不要なものがアンインストールされていました。
アレハンドロ14年

それは面白い。2つ目の出力をPMできますか。1つ目は、3つ目と4つ目の提案を含むコマンドが含まれ、1つは含まれていません プラスの出力uname -r。私にとってはうまくいきます。あなたのケースでなぜ機能しないのかを見るのは面白いでしょう。
マルテスコルッパ14年

1
私はあなたPMにしようとしたが、私はここに私の出力を投稿しますので、私は、任意のメールアドレスを見つけることができませんでした:hastebin.com/raleyigowe.vhdl 事があるということはuname -rのショー私のサーバーは、Linux-画像-3.8.0-34を使用していますサーバーが新しいカーネルをダウンロードしたが、まだインストールしていない場合があります。そのため、古いカーネルのみを削除する方法を探していました。
アレハンドロ14年

このコマンドは、現在のカーネルのヘッ​​ダーファイルを選択しましたが、これは望ましくないようです。
マークストースバーグ

1
@MalteSkoruppaは、をuname -r生成4.8.0-36-generic しますがlinux-headers-4.8.0-36、リストから除外できません。
マークストースバーグ

7

現在起動しているものよりもバージョンが古い「linux- *」パッケージを削除するこのスクリプトを作成しました。パッケージの状態をテストする必要はないと思います。このコマンドは、パッケージをパージする前に確認を求めます。必要ない場合は、apt-getコマンドに-yオプションを追加します。

sudo apt-get purge $(dpkg-query -W -f'${Package}\n' 'linux-*' |
sed -nr 's/.*-([0-9]+(\.[0-9]+){2}-[^-]+).*/\1 &/p' | linux-version sort | 
awk '($1==c){exit} {print $2}' c=$(uname -r | cut -f1,2 -d-))

ただし、構成可能な量のスペアカーネルを残すことができるようにするには、オプション付きのlinux-purgeスクリプトを使用することをお勧めし--keepます。参照してくださいここでスクリプトの詳細については。


3

TL; DR:下にスキップします。

ただし、少し長くなります。分解します。

  1. dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}'マルテが提案したように。関連するカーネルファイルをリストします。
  2. egrep '[0-9]+\.[0-9]+\.[0-9]+' また、バージョン番号を検索してカーネルファイルのみを選択するより安全な方法としてMalteから提案されました。
  3. 現在、画像とヘッダーパッケージの両方をリストしている可能性があるため、パッケージの名前は異なるため、ソートに必要なこのawkの回避策がありますawk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}'。結果は、次のような元のパッケージ名の前のバージョン番号を持つ新しい列です:

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}'
    3.11.0-23 linux-headers-3.11.0-23
    3.11.0-23 linux-headers-3.11.0-23-generic
    3.11.0-24 linux-headers-3.11.0-24
    3.11.0-24 linux-headers-3.11.0-24-generic
    3.11.0-26 linux-headers-3.11.0-26
    3.11.0-26 linux-headers-3.11.0-26-generic
    3.11.0-23 linux-image-3.11.0-23-generic
    3.11.0-24 linux-image-3.11.0-24-generic
    3.11.0-26 linux-image-3.11.0-26-generic
    3.8.0-35 linux-image-3.8.0-35-generic
    3.11.0-23 linux-image-extra-3.11.0-23-generic
    3.11.0-24 linux-image-extra-3.11.0-24-generic
    3.11.0-26 linux-image-extra-3.11.0-26-generic
    3.8.0-35 linux-image-extra-3.8.0-35-generic
  4. 次に、現在実行中のイメージよりも新しいイメージがアンインストールされないように、リストを並べ替える必要があります。sort -k1,1 --version-sort -rこれを私たちに与えます:

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r
    3.11.0-26 linux-image-extra-3.11.0-26-generic
    3.11.0-26 linux-image-3.11.0-26-generic
    3.11.0-26 linux-headers-3.11.0-26-generic
    3.11.0-26 linux-headers-3.11.0-26
    3.11.0-24 linux-image-extra-3.11.0-24-generic
    3.11.0-24 linux-image-3.11.0-24-generic
    3.11.0-24 linux-headers-3.11.0-24-generic
    3.11.0-24 linux-headers-3.11.0-24
    3.11.0-23 linux-image-extra-3.11.0-23-generic
    3.11.0-23 linux-image-3.11.0-23-generic
    3.11.0-23 linux-headers-3.11.0-23-generic
    3.11.0-23 linux-headers-3.11.0-23
    3.8.0-35 linux-image-extra-3.8.0-35-generic
    3.8.0-35 linux-image-3.8.0-35-generic
  5. 次に、現在および新しいカーネルファイルsed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"`を削除して、次のようにします。

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"`
    3.11.0-23 linux-image-extra-3.11.0-23-generic
    3.11.0-23 linux-image-3.11.0-23-generic
    3.11.0-23 linux-headers-3.11.0-23-generic
    3.11.0-23 linux-headers-3.11.0-23
    3.8.0-35 linux-image-extra-3.8.0-35-generic
    3.8.0-35 linux-image-3.8.0-35-generic
  6. 次に、追加した最初の列を削除して、awk '{print $2}'必要なものを正確に取得します。

    $ dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"` | awk '{print $2}'
    linux-image-extra-3.11.0-23-generic
    linux-image-3.11.0-23-generic
    linux-headers-3.11.0-23-generic
    linux-headers-3.11.0-23
    linux-image-extra-3.8.0-35-generic
    linux-image-3.8.0-35-generic
  7. これをパッケージマネージャーにフィードして、すべてを自動的に削除し、grubを再構成できます。

    最初にドライランを実行することをお勧めします(ただし、スクリプト作成の目的では、大規模な環境がある場合、これは実用的ではない場合があります)

    dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"` | awk '{print $2}' | xargs sudo apt-get --dry-run remove

    すべてがよさそうであれば、実際に削除してください:

    dpkg -l linux-{image,headers}-* | awk '/^ii/{print $2}' | egrep '[0-9]+\.[0-9]+\.[0-9]+' | awk 'BEGIN{FS="-"}; {if ($3 ~ /[0-9]+/) print $3"-"$4,$0; else if ($4 ~ /[0-9]+/) print $4"-"$5,$0}' | sort -k1,1 --version-sort -r | sed -e "1,/$(uname -r | cut -f1,2 -d"-")/d" | grep -v -e `uname -r | cut -f1,2 -d"-"` | awk '{print $2}' | xargs sudo apt-get -y purge

繰り返しますが、この「ワンライナー」のポイントは、現在実行中のカーネルよりも古いカーネルのみを削除することです(新しくインストールされたカーネルはまだ利用可能です)

これがどのようにあなたのために働くか、そしてあなたがそれを改善できるかどうかを私に知らせてください!



1

「ls」コマンドを使用して、/ bootディレクトリをリストするだけで、使用しているカーネルのバージョンを確認できます。次に、「sudo apt-get -y purge "xxx"」を使用します。「xxx」は、削除するバージョン番号に置き換えられます。現在実行しているバージョンではないことに注意してください!!。


1
ワンライナーコマンドが必要でした。あなたは解決策を超える1行必要
アンワル


0

簡単な回答、リクエストに応じた説明:

dpkg -l 'linux-image-[0-9]*' | 
awk -v current="$(uname -r)" '!/^i/ || $2~current {next} {print $2}' |
sed '$d' | 
xargs echo sudo apt-get autoremove

2
これを拡張して説明を含めることをお勧めします(または、ご希望の場合はリクエストしてください)。:)
エリアカガン

@EliahKagan、スクリプトは意味をなさないと思います。インストールしたくないパッケージをスキップするのはなぜですか?スクリプトは、現在のカーネルよりも新しいカーネルを削除したり、sed '$d'コマンドによって古いカーネルを保存したりする場合があります。このスクリプトは、削除するカーネルパッケージに関連するlinux-headerパッケージやその他のパッケージを削除しません。さらに、パッケージの構成ファイルも削除しません。代わりに、答えを使用することをお勧めします。
ジャルノ

@EliahKagan実際には、スクリプトはパッケージを削除しませんが、実行可能なコマンドを(byでecho)出力apt-getします。
ジャルノ

0

私はこの不要な複雑さにすべてうんざりして、ワンライナーを簡単にするPythonパッケージを作成しました。

ubuntu-old-kernel-cleanup | xargs sudo apt-get -y purge

でインストール

sudo pip install git+http://github.com/mrts/ubuntu-old-kernel-cleanup.git

詳細についてはhttps://github.com/mrts/ubuntu-old-kernel-cleanupをご覧ください

これが他の人にも役立つことを願っています。


これを試してみましたが、「ubuntu-old-kernel-cleanup:command not found」というエラーが表示されます
付与

その場合、実行可能な検索パスにはありません。sudo pip install ...上記のようにインストールしましたか?sudoこれは実際に重要です。そうしないpipと、ユーザーディレクトリにインストールされ、シェルはこのディレクトリで実行可能ファイルを検索しない場合があります。
-mrts

0
sudo dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge

常に動作し、ubuntu 17.10でも動作します


私にとって、これlinux-libc-dev:amd64は不要なを削除しようとします。
マルテスコルッパ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.