오래된 커널 만 삭제하는 한 줄짜리 강타


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} 결과가 있으므로 현재 커널과 관련된 내용을 제거하지 않도록하십시오.
  • 제거하기 위해 적절한 전화

이것은 작동하지만 적어도 20 대의 서버가 Ubuntu를 실행하기 때문에 솔루션 이보다 우아하고 프로덕션 환경에 안전하다고 확신합니다.

시간 내 주셔서 감사합니다, Alejandro.


인터넷에서 오래된 것 : tuxtweaks.com/2010/10/…
user68186

하나의 라이너가 스크립트 파일에 저장되지 않은 경우 어떻게 사용합니까?
jarno

답변:


25

몇 가지 의견만으로도 충분 해 보입니다. 두 개의 첫 번째 주석은 명령을 더 안전하게 만드는 반면, 세 번째 및 네 번째 주석은 명령을 조금 짧게 만듭니다. 그들 중 하나를 따르거나 무시하십시오. 비록 처음 두 가지를 따르는 것이 좋습니다. 가능한 한 안전한지 확인하고 싶습니다. 진심이야 sudo apt-get -y purge자동으로 생성 된 패키지 목록을 던지고 있습니다. 너무 악하다 ! :)

  1. 모두 나열 linux-*하면 (예 : 내 출력 결과)와 같은 많은 오 탐지를 얻을 수 있습니다 linux-sound-base. 나중에 나머지 명령으로 필터링 할 수 있지만 처음에는 목록을 표시하지 않는 것이 더 안전합니다. 제거하려는 패키지를보다 잘 제어하십시오. 예기치 않은 결과가 발생할 수있는 일을하지 마십시오. 그래서 시작하겠습니다

    dpkg -l linux-{image,headers}-*
  2. "숫자가있는 것만 나열"하는 정규식은 제 생각에는 너무 단순합니다. 예를 들어 linux-libc-dev:amd6464 비트 시스템에있을 때 패키지 가 있습니다. 정규식이 일치합니다. 당신은 그것을 일치시키고 싶지 않습니다. 틀림없이, 당신이 나의 첫 번째 조언을 따른다면 linux-libc-dev:amd64어쨌든 등재되지는 않을 것입니다. 우리는 단순한 숫자 "숫자가 있습니다"보다 버전 번호의 구조에 대해 더 많이 알고 있습니다. 또한 일반적으로 쉘에 의한 잠재적 인 오해를 막기 위해 정규 표현식을 인용하는 것이 좋습니다. 그래서 그 egrep 명령을 만들 것입니다

     egrep '[0-9]+\.[0-9]+\.[0-9]+'
  3. 그러면이 분류가 있습니다. 왜 정렬합니까? 어쨌든 모든 커널 (현재 커널 제외)을 제거 할 것이므로, 새로운 커널보다 이전 커널을 제거하는 것이 중요합니까? 나는 그것이 아무런 차이가 없다고 생각합니다. 아니면 sed"현재 커널 다음에 나오는 결과 만 인쇄" 하는 데 사용할 수 있습니까? 그러나 IMO는 너무 복잡하다고 느낍니다. grep -v어쨌든 이미 수행하고있는 것처럼 현재 커널에 해당하는 결과를 간단히 필터링하지 않는 이유는 무엇 입니까? 솔직히, 내가 당신의 명령의 첫 번째 부분을 가져 가면 (내 두 가지 이전 제안이 통합되어 있음) 내 컴퓨터에서

    $ 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

    그 정렬 / sed 물건을 제거하면

    $ 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

    따라서 더 복잡한 명령은 실제로 내 컴퓨터에서 두 개의 패키지를 놓치므로 제거하고 싶습니다 (이러한 것이 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, 귀하의 의견에 감사드립니다. 나는 당신의 두 가지 첫 단계가 매우 명확하다는 것을 알았습니다. 그러나 마지막 두 단계는 최신 커널을 무시하고 제거합니다. 적어도 내 서버에서 솔루션을 시도했지만 원치 않는 것을 제거했을 것입니다.
Alejandro

그 흥미 롭군요. 두 번째 출력, 하나는 세 번째와 네 번째 제안이 포함 된 명령을 사용하고 하나는 출력하지 않고 두 개의 출력을 나에게 보내 줄 수 있습니까? 의 출력을 더한 것입니다 uname -r. 나를 위해 그것은 잘 작동합니다. 왜 귀하의 경우에는 작동하지 않는지 보는 것이 흥미로울 것입니다.
Malte Skoruppa

1
나는 당신을 오후하려고했지만 이메일 주소를 찾지 못했습니다. 내 출력을 여기에 게시 할 것입니다 : hastebin.com/raleyigowe.vhdl uname -r 내 서버가 linux-image-3.8.0-34를 사용하고 있음을 보여줍니다. 때로는 서버가 최신 커널을 다운로드했지만 아직 설치하지 않았습니다. 그렇기 때문에 오래된 커널 제거하는 방법을 찾고있었습니다 .
Alejandro

이 명령은 현재 커널에 대한 헤더 파일을 선택했는데 바람직하지 않습니다.
Mark Stosberg

1
@MalteSkoruppa가 uname -r생성 하여 목록에서 4.8.0-36-generic 제외하지 못했습니다 linux-headers-4.8.0-36.
Mark Stosberg

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}'Malte가 제안한 것처럼. 관련 커널 파일을 나열합니다.
  2. egrep '[0-9]+\.[0-9]+\.[0-9]+' Malte는 버전 번호를 찾아 커널 파일 만 선택하는보다 안전한 방법으로 제안했습니다.
  3. 이제 이미지와 헤더 패키지를 모두 나열 할 수 있으므로 패키지 이름이 다를 수 있으므로 정렬에 필요한 해결 방법 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

다시 한 번이 "한 줄짜리"의 요점은 현재 실행중인 커널보다 커널 OLDER 만 제거하는 것입니다 (새로 설치된 커널을 계속 사용할 수 있음)

이것이 어떻게 작동하는지, 개선 할 수 있는지 알려주십시오.


답변
jarno

1

'ls'명령을 사용하는 커널 버전을 보려면 / boot 디렉토리를 간단히 나열하면됩니다. 그런 다음 'sudo apt-get -y purge "xxx"'를 사용하십시오. 여기서 "xxx"는 제거하려는 버전 번호로 바뀝니다. 현재 실행중인 버전이 아닌지 확인하십시오 !!.


1
그들은 하나의 라이너 명령을 원했습니다. 솔루션은 한 줄 이상이 필요합니다
Anwar


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
설명을 포함하도록이를 확장 (또는 원하는 경우 요청) 할 것을 제안합니다. :)
Eliah Kagan

@ EliahKagan, 나는 스크립트가 이해가되지 않는다고 생각합니다. 설치하지 않으려는 패키지를 건너 뛰는 이유는 무엇입니까? 스크립트는 현재 커널보다 새로운 커널을 제거하거나 sed '$d'명령에 의해 이전 커널을 저장할 수 있습니다 . 스크립트는 제거 할 커널 패키지와 관련된 linux-header 패키지 또는 기타 패키지를 제거하지 않으며 패키지의 구성 파일을 삭제하지 않습니다. 대신 내 대답을 사용하는 것이 좋습니다.
jarno

@EliahKagan 실제로 스크립트는 패키지를 제거하지 않지만 실행할 수 echo있는 apt-get명령을 인쇄 합니다.
jarno

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 에서 자세한 내용을 참조하십시오 .

이것이 다른 사람들에게도 도움이되기를 바랍니다.


이것을 시도했지만 오류가 발생했습니다 : "우분투-오래된 커널 정리 : 명령을 찾을 수 없습니다"
Grant

그런 다음 실행 가능한 검색 경로에 없습니다. 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

항상 작동하며 심지어 우분투 17.10


나를 위해 이것은 제거하려고 시도합니다 linux-libc-dev:amd64.
Malte Skoruppa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.