• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[TIP] apt cache aufräumen

Status
Für weitere Antworten geschlossen.

oc2pus

Ultimate Guru
hier mal ein kleines Tool um den apt cache (normalerweise /var/cache/apt/*) etwas aufzuräumen.

Es ist eine Kombination aus einem Python-Script und einem kleinen C-Programm zum Versionsvergleich.
Ich habe diese beiden Tools einfach mal kombiniert :)

Teil 1: Python Script apt-smartclean.py
Code:
#! /usr/bin/python
#  GPL v2 code. Radim Kolar <hsn/at/cybermail.net>
#  http://home.tiscali.cz/~cz210552/
#  modified for rpm Distris by oc2pus
#
#  APT-SMARTCLEAN
#
#  This programs cleans APT package cache directory. Unlike apt-get autoclean,
#  it leaves in cache directory only last version of package even if this
#  package is no longer available for download. This is less aggressive
#  cleaning than autoclean does.
#
#  ARGUMENTS -s  ... dry run
#
#  Changelog
#
#    VERSION 1 - 18 Aug 2003 First version
#    VERSION 1.1 - 14 Dec 2004 modifications for rpm based distris

import os
import sys

def cleanaptcache(dryrun=0,dirs=('/var/cache/apt/archives/','/var/cache/apt/archives/partial/')):
    for dir in dirs:
       packages={} # versions
       fnames={}   # file names
       for file in os.listdir(dir):
	  if file[-4:] != '.rpm': continue
	  parsed=file.split('_')
	  if len(parsed) != 3: continue
	  parsed[1]=parsed[1].replace('%3a',':')
	  if packages.has_key(parsed[0]):
	      print 'Found',parsed[0],parsed[1],'have',packages[parsed[0]]
              # 1:  a is newer than b
              # 0:  a and b are the same version
              # -1: b is newer than a 
              #  2: wrong arguments number	      
	      argz=['rvc',parsed[1],packages[parsed[0]]]
	      rc=os.spawnvp(os.P_WAIT,'./rvc',argz)
	      if rc==0: 
		 print "skipping",fnames[parsed[0]]
	         continue
	      if rc==255:
		 print "\tDeleting",dir+file
		 if not dryrun: os.unlink(dir+file)
		 continue
	      elif rc==1:
		 print "\tDeleting",dir+fnames[parsed[0]]
		 if not dryrun: os.unlink(dir+fnames[parsed[0]])
		 
	  packages[parsed[0]]=parsed[1]
	  fnames[parsed[0]]=file

if __name__=="__main__":
    sys.stdout.write("Running on SuSE\n")
    sys.stdout.flush()
    if len(sys.argv)>1 and sys.argv[1]=='-s':
	dryrun=1
	print "Dry run is enabled. Not deleting anything."
    else:
	dryrun=0
    cleanaptcache(dryrun)

Teil 2a: C-Programm rvc.c
Code:
/* 
 * $Id: rvc.c,v 1.5 2002/10/27 18:27:23 luigi Exp $
 ******
 * rvc.c - RPM Version Compare 
 * Given two strings representing a different version and release 
 * of a single rpm package, it returns which one is newer or, 
 * alternatively, an error.
 * 
 * parameters 
 *        two strings (a and b) structured in the following way:
 *        <RPM_version>-<RPM_release>. 
 * 
 * return values
 *        1: a is newer than b
 *        0: a and b are the same version
 *       -1: b is newer than a 
 *        2: wrong arguments number
 * 
 * The assumption the two strings to compare are "logically coherent" 
 * is made, otherwise you will probably end up being told that b is 
 * newer than a (something which happens in this kind of situation)..
 * The rpmvercmp function is "borrowed" from the Redhat package manager 
 * (RPM 4.1), as are all the inline functions in the header file 
 * (rpmvercmp.h).
 *
 ******
 *
 *   Copyright 2002 Luigi Bitonti
 *   
 *   Copyright 2002 Redhat Inc.
 *
 *   This file is part of rvc (RPM version compare).
 *
 *   rvc is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   rvc is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with rvc; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


#include "rvc.h"


int 
main(int argc, char **argv)
{

    /* We need exactly two arguments for the comparison */
    if (argc != 3)
    {
      fprintf(stderr, "Usage: %s <RPM_versionA>-<RPM_releaseA> <RPM_versionB>-<RPM_releaseB>", argv[0]);
      return 2;
    }

    return rpmvercmp(argv[1], argv[2]);      
}


/* compare alpha and numeric segments of two versions */
/* return 1: a is newer than b */
/*        0: a and b are the same version */
/*       -1: b is newer than a */
int 
rpmvercmp(const char * a, const char * b)
{
    char oldch1, oldch2;
    char * str1, * str2;
    char * one, * two;
    int rc;
    int isnum;

    /* easy comparison to see if versions are identical */
    if (!strcmp(a, b)) return 0;

    str1 = alloca(strlen(a) + 1);
    str2 = alloca(strlen(b) + 1);

    strcpy(str1, a);
    strcpy(str2, b);

    one = str1;
    two = str2;

    /* loop through each version segment of str1 and str2 and compare them */
    while (*one && *two)
    {
	while (*one && !xisalnum(*one)) one++;
	while (*two && !xisalnum(*two)) two++;

	str1 = one;
	str2 = two;

	/* grab first completely alpha or completely numeric segment */
	/* leave one and two pointing to the start of the alpha or numeric */
	/* segment and walk str1 and str2 to end of segment */
	if (xisdigit(*str1))
	{
	    while (*str1 && xisdigit(*str1)) str1++;
	    while (*str2 && xisdigit(*str2)) str2++;
	    isnum = 1;
	} else {
	    while (*str1 && xisalpha(*str1)) str1++;
	    while (*str2 && xisalpha(*str2)) str2++;
	    isnum = 0;
	}

	/* save character at the end of the alpha or numeric segment */
	/* so that they can be restored after the comparison */
	oldch1 = *str1;
	*str1 = '\0';
	oldch2 = *str2;
	*str2 = '\0';

	/* take care of the case where the two version segments are */
	/* different types: one numeric, the other alpha (i.e. empty) */
	if (one == str1) return -1;	/* arbitrary */
	if (two == str2) return -1;

	if (isnum)
	{
	    /* this used to be done by converting the digit segments */
	    /* to ints using atoi() - it's changed because long  */
	    /* digit segments can overflow an int - this should fix that. */

	    /* throw away any leading zeros - it's a number, right? */
	    while (*one == '0') one++;
	    while (*two == '0') two++;

	    /* whichever number has more digits wins */
	    if (strlen(one) > strlen(two)) return 1;
	    if (strlen(two) > strlen(one)) return -1;
	}

	/* strcmp will return which one is greater - even if the two */
	/* segments are alpha or if they are numeric.  don't return  */
	/* if they are equal because there might be more segments to */
	/* compare */
	rc = strcmp(one, two);
	if (rc < 0) 
	    return -1;
	else if (rc > 0)
	    return 1;

	/* restore character that was replaced by null above */
	*str1 = oldch1;
	one = str1;
	*str2 = oldch2;
	two = str2;
    }

    /* this catches the case where all numeric and alpha segments have */
    /* compared identically but the segment sepparating characters were */
    /* different */
    if ((!*one) && (!*two)) return 0;

    /* whichever version still has characters left over wins */
    if (!*one) return -1; else return 1;
}

Teil 2b: rvc.h
Code:
/*
 * $Id: rvc.h,v 1.4 2002/10/27 18:28:00 luigi Exp $
 **
 * rvc.h - include file for rvc.c
 *
 *   Copyright 2002 Luigi Bitonti
 *   
 *   Copyright 2002 Redhat Inc.
 *
 *   This file is part of rvc (RPM version compare).
 *
 *   rvc is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   rvc is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with rvc; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>


int rpmvercmp(const char *, const char *);


static inline int xislower(int c) {
    return (c >= 'a' && c <= 'z');
}

static inline int xisupper(int c) {
    return (c >= 'A' && c <= 'Z');
}

static inline int xisalpha(int c) {
    return (xislower(c) || xisupper(c));
}

static inline int xisdigit(int c) {
    return (c >= '0' && c <= '9');
}

static inline int xisalnum(int c) {
    return (xisalpha(c) || xisdigit(c));
}

static inline int xisblank(int c) {
    return (c == ' ' || c == '\t');
}

static inline int xisspace(int c) {
    return (xisblank(c) || c == '\n' || c == '\r' || c == '\f' || c == '\v');
}

static inline int xtolower(int c) {
    return ((xisupper(c)) ? (c | ('a' - 'A')) : c);
}

static inline int xtoupper(int c) {
    return ((xislower(c)) ? (c & ~('a' - 'A')) : c);
}

Teil 2c: Makefile
Code:
# $Id: Makefile,v 1.2 2003/03/06 17:54:19 luigi Exp $
# Makefile for rvc (RPM version compare)

CC = gcc
CFLAGS = -Wall

all : rvc

rvc : rvc.c  rvc.h
	${CC}  ${CFLAGS}  -o  $@  $<

Installation:
Das C-Programm wird umgewandelt mit dem Aufruf make. Dadurch wird ein Programm rvc erstellt.
Wer seinen apt-cache in einem anderen Verzeichnis stehen hat als /var/apt/cache sollte in dem Python-Script den Pfad anpassen.
Beide Programmteile dann nach /usr/local/bin kopieren
cp rvc /usr/local/bin
cp apt-smartclean.py /usr/local/bin

Der Aufruf
Code:
apt-smartclean.py -s
zeigt an was obsolet im Cache rumsteht. Mit dem Aufruf
Code:
apt-smartclean.py
werden die obsoleten RPMs aus dem cache gelöscht.

Ich finde ein schönes Beispiel wie man zwei vorhandene Tools einfach kombiniert und schnell ein brauchbares Ergebnis erzielt.

Dieses Script hat für mich wunderbar funktioniert. Aber ich übernehme keine Haftung für die Anwendung und evtl Schäden an eurem System.
 
OP
oc2pus

oc2pus

Ultimate Guru
Hier noch eine Alternative:

1.) Download des Python-Scriptes von hier:
http://home.tiscali.cz:8080/~cz210552/distfiles/apt-smartclean.py

2.) diesen Patch als apt-smartclean-rpm.diff abspeichern:
Code:
--- apt-smartclean.py   2004-12-15 11:29:45.384724472 +0100
+++ apt-smartclean-rpm.py       2004-12-15 11:30:28.928104872 +0100
@@ -24,7 +24,7 @@
        packages={} # versions
        fnames={}   # file names
        for file in os.listdir(dir):
-         if file[-4:] != '.deb': continue
+         if file[-4:] != '.rpm': continue
          parsed=file.split('_')
          if len(parsed) != 3: continue
          parsed[1]=parsed[1].replace('%3a',':')
@@ -47,7 +47,7 @@

 if __name__=="__main__":
     #working dpkg test
-    sys.stdout.write("Running on Debian-")
+    sys.stdout.write("Running on SuSE-")
     sys.stdout.flush()
     rc=os.spawnlp(os.P_WAIT,'dpkg','dpkg','--print-architecture')
     if rc!=0:

3.) mit patch -p0 < apt-smartclean-rpm.diff das Script patchen
damit wird das portierte dpkg von debian für den Versionsvergleich genutzt.

4.) mit apt install deb das Paket deb installieren

5.) apt-smartclean.py installieren
cp apt-smartclean.py /usr/local/bin
 
OP
oc2pus

oc2pus

Ultimate Guru
ok, wenn cut & paste soooo schwierig ist ....

die RPMs liegen in meinem Repository suser-oc2pus.
apt install apt-smartclean

die RPMs gibt es hier:
http://ftp.gwdg.de/pub/linux/suse/apt/SuSE/8.2-i386/RPMS.suser-oc2pus
http://ftp.gwdg.de/pub/linux/suse/apt/SuSE/9.1-i386/RPMS.suser-oc2pus
http://ftp.gwdg.de/pub/linux/suse/apt/SuSE/9.2-i386/RPMS.suser-oc2pus
http://ftp.gwdg.de/pub/linux/suse/apt/SuSE/9.3-i386/RPMS.suser-oc2pus
http://ftp.gwdg.de/pub/linux/suse/apt/SuSE/10.0-i386/RPMS.suser-oc2pus
http://ftp.gwdg.de/pub/linux/suse/apt/SuSE/10.1-i386/RPMS.suser-oc2pus
...
 

michael_33

Member
Hallo,

kannst Du das bitte noch für suse9.0 reinstellen, dann kann ich es nähmlich auch gebrauchen ... 8)

thx
michael
 
OP
oc2pus

oc2pus

Ultimate Guru
michael_33 schrieb:
kannst Du das bitte noch für suse9.0 reinstellen, dann kann ich es nähmlich auch gebrauchen ... 8)

nein kann ich leider nicht ;)
aber da es ein noarch.rpm ist, kannst du es downloaden und manuell installieren.

oder du nimmst das src.rpm und wandelst es in ein rpm um für 9.0

oder du kopierst die sourcen von oben ...
 

Tux-Manni

Member
Hallo

Gibt es ev eine readme zu apt-smartclean? Hab es per apt installiert, inklusive deb. Allerdings scheint das nicht zu laufen.
Oder fehlt dazu noch etwas?
Zum anderen: reicht nicht auch ein rm /var/cache/apt/archives/*.rpm ?

Danke für Aufklärung
Manni
 
OP
oc2pus

oc2pus

Ultimate Guru
Tux-Manni schrieb:
Gibt es ev eine readme zu apt-smartclean? Hab es per apt installiert, inklusive deb. Allerdings scheint das nicht zu laufen.
Oder fehlt dazu noch etwas?
Zum anderen: reicht nicht auch ein rm /var/cache/apt/archives/*.rpm ?

nein gibt es nicht. Wofür auch ...
apt-smartclean -s ==> Simulation, was entfernt würde
apt-smartclean ==> es wird gelöscht

apt-smartclean sorgt dafür das im Cache die jeweils aktuellste RPM Version übrigbleibt, unabhängig davon ob apt diese Version noch erreichen kann auf einem Server!

rm /var/cache/apt/archives/*.rpm löscht alles im cache. Nette Idee, aber mach dir mal den Sinn eines cache klar ;)
 
Status
Für weitere Antworten geschlossen.
Oben