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

[Tipp] Einführung in das Concurrent Versions System (CVS)

shattered

Member
CVS - CONCURRENT VERSIONS SYSTEM

EINFÜHRUNG

ENTSTEHUNGSGESCHICHTE

CVS entstand mit dem Aufkommen von freier Software. Treibende Kräfte waren Richard Stallman (Gründer der Free Software Foundation), Eric Raymond (dokumentierte das Open-Source Phänomen und veröffentlichte wegweisende Abhandlungen) und natürlch Linus Torvalds sowie einige andere.

Stallman arbeitete 1970 am Massachusetts Institute of Technology im Labor für künstliche Intelligenz. In dieser Umgebung wurden schon früh alle Quelltexte geteilt. Persönliche Veränderungen am Code im Sinne von Besitz gab es nicht, alles gehörte der Gemeinschaft. Um 1980 wurden die meisten Entwickler jedoch von Unternehmungen aufgekauft und für proprietäre Projekte eingesetzt, was natürlich hiess, dass sie den Quelltext von nun an zurückhalten mussten.

Dies war für Stallman nicht tolerierbar; er gründete die "Free Software Foundation" (1990) und begann, ein vollständig freies Betriebssystem zu schreiben, welches er GNU (GNU's not Unix) nannte. Ebenso entwickelte er die GNU Public License - GPL - welche öffentlich gemachte Quelltexte schützen und deren restriktive Verbreitung verhindern sollte.

Zur (fast) gleichen Zeit wurde publik, dass der finnische Student Linux Torvalds an einem Betriebssystem (Linux) arbeitete, welches einen vollständigen Unix-Kern auf der Basis der GPL neu implementieren würde. Dies hat das Open-Source Prinzip deutlich vorangetrieben.

Die freie Softwarebewegung musste jedoch rasch feststellen, dass sie grosse logistische Probleme hatte. Der offene Code wurde durch die rasend wachsende Zahl von Entwicklern schnell unkontrollierbar. Mit dem Aufkommen von Netzwerken und dem Internet wurde die Situation noch prekärer. Also kam der Ruf nach einem System auf, welches Quellcode effizient managen und Änderungen protokollieren kann.

Zuerst wurden die Tools "diff" (zeigt der Unterschied zweier Quelltexte auf) und "patch" (implementiert diese Unterschiede in eine Datei) programmiert. Dennoch gab es weiterhin grosse Probleme, das manuelle zurücknehmen eines Patches war zum Beispiel sehr zeitaufwändig und eine "history" der Änderungen gab es auch nicht. So wurde von Walter Tichys das Revision Control System - RCS - entwickelt. Es erlaubte zwar obige Dinge, hatte aber einige Mängel; die Dateien eines Projektes standen in keinster Beziehung zueinander und das "Sperren-Modifizieren-Freigeben" System war ineffizient.

Das Concurrent Versions System - CVS - sollte dies beheben. Es war am Anfang nichts weiter als ein mit Skripte ergänztes RCS, wurde dann aber schnell eigenständig und im Jahre 1990 auch netzwerkfähig. Es erlaubte erstmals eine strukturierte simultane Entwicklung mit einem intelligenten Zusammenführen von Veränderungen und wurde inner kürzester Zeit zum de-facto Standard für viele open-source (als auch proprietäre) Projekte, was es bis heute geblieben ist!

DIE GRUNDLAGEN VON CVS

CVS wird für zwei scheinbar unabhängige Aufgaben benutzt: Historienverwaltung und Zusammenarbeit. Sie gehen jedoch Hand in Hand, weil das Ausmerzen von schlecht implementierten Codes in einer Gruppe von Programmierern ohne eine Versionsverwaltung gar nicht möglich ist.

Die Hauptkopie (Repository) eines Projektes ist nichts weiter als ein Datei-/Verzeichnisbaum, der auf einem Server gespeichert ist. Den holt man sich, bevor man mit dem Coden beginnt und aktualisiert ihn, wenn man damit fertig ist. Wird ein Konflikt angezeigt, ist ein "commit" nicht möglich. In diesem Falle muss der Entwickler zuerst die Probleme auflösen und kann seine veränderte Version erst dann zum Server hochladen. CVS speichert alle Veränderungen als "diff" und führt eine Historie, wodurch es möglich ist, verschiedene Revisionen einer Datei miteinander zu vergleichen und ältere wiederherzustellen.

Was CVS nicht ist/kann

- Das Entwicklungsmodell "Sperren-Ändern-Freigeben" wird nicht verwendet
- Dateisperren sind zwar möglich, aber nicht zu empfehlen
- CVS ersetzt nicht die Kommunikation zwischen den Entwicklern
- CVS löst Konflikte (gleichzeitig veränderter Quellcode in der gleichen Datei) nicht automatisch
- Der Umgang mit Binärdateien ist nicht sehr elegant

Was CVS ist/kann

- Das Entwicklungsmodell "Konzipieren-Modifizieren-Zusammenfassen"

1. Der Entwickler fordert eine Arbeitskopie von CVS an (checkout)
2. Der Entwickler arbeitet lokal an seiner Kopie (sandbox)
3. Der Entwickler sendet seine Veränderunge mit einem Log ans CVS (commit)

- Philosophie der funktionierenden Haupkopie (Veränderungen erst abschicken, wenn sie funktionieren)
- Erkennung von Konflikten (gleichzeitig veränderter Quellcode in der gleichen Datei)

TERMINOLOGIE

Checkout: Anfordern einer Arbeitskopie aus dem Archiv (z.B. einer alten Revision)
Commit/Checkin: Senden der eigenen Veränderungen zum Archiv
Revision: Eine Momentaufnahme einer Datei bzw. eines Projektes (z.B. die Revision 1.7)
Konflikt: Gleichzeitige Veränderung des gleichen Codes in der gleichen Datei
Log: Angehängter Kommentar bei einem Commit
Archiv: Die Haupkopie inkl. gespeicherte Historie (auf dem Server)
Update: Aufnahme der aktuellen Veränderungen anderer Entwickler in die eigene Arbeitskopie
Sandbox: Die (lokale) Arbeitskopie an der ein Entwickler gerade arbeitet
Binärdatei: Alles, was keine Textdatei ist

Alternativen

- BitKeeper
- Subversion
- Microsoft VSS
- RCS und CSRCS und GNU/RCS
- Perforce
- SCCS

DIE CLIENT-KOMMANDOS IN EINER UNIX UMGEBUNG

Bevor wir loslegen, noch ein kleiner Hinweis:

Ein CVS Arbeitsverzeichnis darf NIE Unterverzeichnisse namens CVS enthalten!

Syntax: cvs (globale Optionen) Kommando (Kommando-Optionen)
Beispiel: cvx -Q update -p

Zugriff auf das Archiv und Login

Der Ort des Archivs muss nur einmal angegeben werden, nämlich beim ersten checkout, lokal zum Beispiel:

cvs -d /usr/local/cvs Kommando

In einem Netzwerk sieht es so aus:

cvs -d :Zugriffsmethode:Benutzername@Servername:Archivverzeichnis login

(es gibt mehrere unterschiedliche Zugriffsmethoden)

zum Beispiel:

cvs -d :pserver:jrandom@cvs.foobar.com:/usr/local/cvs login

Die Passwort-Abfrage geschieht bei der pserver Methode nach Eingabe des Kommandos, es wird dann auch gleich im Home unter .cvspass abgespeichert und muss nur einmal eingegeben werden.

Alternative Verbindungsprotokolle sind:

- rsh/ssh :)ext:)
- kserver
- gserver

Will man ssh verwendet, führt man dies aus:

CVS_RSH=ssh
export CVS_RSH

und unter Windows folgendes:

set CVS_RSH=ssh

Verwendet man nur ein Archiv und will nicht jedesmal -d repository eingeben:

[lokal]

CVSROOT=/usr/local/cvs
export CVSROOT
echo $CVSROOT

oder

[extern]

CVSROOT=:pserver:jrandom@cvs.foobar.com:/usr/local/cvs
export CVSROOT
echo $CVSROOT

Achtung:

Der Rest der Ausführungen geht davon aus, dass die CVSROOT entsprechend definiert wurde, die Option -d wird also jeweils weggelassen. Die Umgebungsvariable sollte aber nur dann gesezt werden, wenn man lediglich auf ein Archiv zugreift!

Ein neues Projekt importieren

cd projektname
cvs import -m "das projekt wird hiermit eröffnet" projektname johannes start
cd..
ls
mv projektname sicherung_projektname

Arbeiskopie auschecken

cvs checkout projektname

Eine Veränderung vornehmen

Texteditor seiner Wahl starten und die Änderung vornehmen.

update und diff - wer hat was verändert?

update: Veränderungen aus dem Archiv (vom Server) in die eigene Arbeitskopie einfliessen lassen

cvs update
cvs update -d

(mit der Option -d holt man neue Verzeichnisse aus dem Archiv in das Arbeitsverzeichnis)

---> welche dateien habe ich bearbeitet?

cvs -q update

(oder ohne -q für eine erweiterte Ausgabe)

Steht ein M vor der Ausgabe ist die Datei lokal nicht einheitlich mit dem Archiv.

---> was genau habe ich bwz. hat sich geändert?

cvs -Q diff -c

commit durchführen

cvs commit -m "bug gefixt" hello.c

Optionen auf nur eine Datei bwz. ein Unterverzeichnis anwenden

z.B. update von mehreren Dateien: (nicht üblich!)

cvs update hello.c goodbye.c unterverzeichnis/salut.c

Veränderung einer einzelnen Datei:

cvs diff -c hello.c

und so weiter...

Kurzformen anfragen

vereinfachen die Eingabe...

cvs --help-synonyms

Revisionsnummern und Status herausfinden

cvs -Q status
cvs -Q status hello.c

Konflikte erkennen und auflösen

Syntax des Konfliktes:

<<<<<<<< (Dateiname)
Veränderungen der Arbeitskopie
========
neue Änderungen aus dem Archiv
>>>>>>>> (letzte Revisionsnummer des Archivs)

Editor öffnen, ändern und Konflikmarkierungen entfernen, erneuter commit!

Log-Nachrichten lesen

cvs log
cvs log hello.c

Veränderungen untersuchen und zurücknehmen

ACHTUNG: Das sollte auf jeden Fall unter den Entwicklern abgesprochen werden!

Vergleich von zwei Revisionen:

cvs diff -c -r 1.3 -r 1.4 hello.c

Revision zurücknehmen:

(z.B. von 1.4 zurück auf 1.3 --> erzeugt trotzdem die 1.5 damit es in historie einsehbar ist!)

Der langsame Weg (mühsam!)

cvs update
cvs -Q update -p -r 1.3 hello.c > hello.c
cvs update
cvs commit -m "zurück auf die 1.3"

Der schnelle Weg

cvs update -j 1.4 -j 1.3 hello.c

(patcht die 1.4 zurück auf die 1.3)

Dateien hinzufügen

cvs add newfile.c
cvs commit -m "neue datei hinzugefügt" newfile.c

Verzeichnisse hinzufügen

mkdir neuesverzeichnis
cvs add neuesverzeichnis

(commit ist im Gegensatz zum obigen Befehl nicht nötig)

Dateien entfernen

rm oldfile.c
cvs remove oldfile.c
cvs commit -m "unnötige datei entfernt" oldfile.c

(die Datei also zuerst aus dem Arbeitsverzeichnis entfernen)

Hinzufügen einer Binärdatei

cvs -add -kb dateiname
cvs commit -m "binärdatei hinzugefügt" dateiname

(schaltet Schlüsselwortersetzung und Zeilenumwandlung aus)

Achtung: diffs zwischen Binärdateien sind nicht möglich!

Schlüsselwortkennung abschalten und so Datei hinzufügen

cvs add -ko dateiname
cvs commit -m "datei ohne schlüsselworterkennung hinzugefügt" dateiname

Verzeichnisse entfernen

Achtung: Verzeichnisse stehen nicht unter der Versionskontrolle, nur Dateien

cd blabla
rm datei1 datei2 datei3 dateix
cvs remove datei1 datei2 datei3 dateix
cvs commit -m "das verzeichnis blabla entfernt" datei1 datei2 datei3 dateix
cd ..
cvs update -P

(zuerst löschen, dann remove und commit, dann update -P eine Ebene höher)

In der Arbeitskopie ist das Verzeichnis nun weg, im Archiv existiert eine leere Kopie.

Dateien und Verzeichnisse umbenennen

cp altername neuername
rm altername

ist ja im Prinzip eine Umbennenung auf Unix.

bei CVS geht es genau gleich:

mv altername neuername
cvs remove altername
cvs add neuername
cvs commit -m "altername in neuername umbenannt" altername neuername

bei Verzeichnissen geht es so:

Achtung: Das ist zwar machbar, aber sehr mühsam.

mkdir neuesverzeichnis
cvs add neuesverzeichnis
mv altesverzeichnis/* neuesverzeichnis #hier kommt ne' warnung, kann man ignorieren
cd altesverzeichnis
cvs remove datei1 datei2 dateix
cd ../neuesverzeichnis
cvs add datei1 datei2 dateix
cd ..
cvs commit -m "datei1 und datei1 von neuesverzeichnis in altesverzeichnis geschoben"
cvs update -P

Optionen standardmässig ausführen

die .cvsrc im Home bearbeiten, z.B. so:

diff -c
update -p
cvs -q

also wird in Folge diff immer als diff -c ausgeführt, update immer als update -p etc.

Komplette Momentaufnahme holen und vergleichen

A. Datums-Bezogen

cvs -q update -D "2004-04-19"

Achtung: Das wird als "Mitternacht beginnend am 19. April" interpretiert.

darum zum Beispiel:

cvs -q update -D "2004-04-19 23:59:59"

Achtung: Das Archiv speichert die Zeit in UCT (GMT) - das Arbeitsverzeichnis hingegen in der lokalen Zeit

darum:

cvs -q update -D "2004-04-19 23:59:59 GMT"

Achtung: Die Arbeitskopie wird damit (-D) auf dieses vergangene Datum festgelegt und is sticky.

Bei einem anschliessenden cvs update passiert also gar nichts, obwohl neuere Dateien vorhanden wären!

Achtung: diffs sind natürlich weiterhin möglich

cvs -q diff -c -r 1.5 hello.c

B. Markierungs-Bezogen

Eine Markierung setzen

Wenn ein Projekt stabil läuft, markiert man am besten alle Änderungen in einem tag:

cvs -q Release-2004_05_01

Eine Momentaufnahme ist also eine Gruppe von Dateien mit ihren Revisionsnummern innerhalb eines Projektes.

Achtung: Markierungsnamen sollten so knapp wie möglich gehalten werden.

Ein gültiger Markierungsname

1. er enthält keine Leerzeichen, Punkte, Doppelpunkte, Kommas und andere Symbole
2. er beginnt und endet mit einem Buchstaben

(zulässig sind Buchstaben, Ziffern, Bindestriche und Unterstriche)

Achtung: Eine Revisionsnummer hat einen Punkt, eine Markierung nicht.

a) Momentaufnahme holen durch checkout

Achtung: Dies nicht im Verzeichnis der existierenden Arbeitskopie machen.

Zuerst diff angucken:

cvs diff -c -r Release-2004_05_01 hello.c

zurückgehen:

cvs update -r Release-2004_05_01 hello.c

gesamt:

cvs checkout -r Release-2004_05_01

b) Momentaufnahme holen durch Markierung

cvs update -r Release-2004_05_01

Achtung: Bei a) und b) ist das Arbeitsverzeichnis nun sticky und es sind keine Commits mehr möglich.

Man kann die Vergangenheit also so nicht verändern!

Sticky Status checken

cvs -q update -D "2004-04-19 23:59:59 GMT"

Sticky Status entfernen und Arbeitskopie wieder auf den neuesten Stand bringen

cvs -q update -A

Achtung: Dabei gehen Veränderungen an einer Datei nicht verloren

sprich: ein cvs -q diff -c hello.c gibt weiter die Veränderung aus.

Ist der sticky Status entfernet, sind commits wieder möglich:

cvs commit -m "kommentar hinzugefügt"

jetzt kann man vergleichen:

cvs -q status hello.c

Gültige Datumsformate

ISO 8691-Format oder die E-Mail-Formate RFC 822 und RFC 1123

Beispiele:

"19 Apr 2004"
"19 Apr 2004 20:05"
"19/04/2004"
"3 days ago"
"5 years ago"
"19 Apr 2004 23:59:59 GMT"
"19 Apr"

Verzweigungen

Ziel: CVS erlaubt durch Verzweigungen das Verändern der Vergangenheit.

Dadurch spaltet man die Entwicklung eines Projektes in getrennte, parallele Zweige. Veränderungen an einem Zweig betreffen den anderen nicht mehr. Muss man einen alten Fehler rückgängig machen, ist es falsch, zuerst eine alte Version auszuchecken und diese dann zu verändern, weil dies nicht in der "history" verzeichnet wird und später nicht mehr nachvollziehbar oder rückgängig machbar ist. In der aktuellsten Version sollte man den Fehler auch nicht beheben, da sie instabil sein könnte.

So geht man zurück zur letzten stabilen, öffentlichen Version spaltet einen Etwicklungszweig (trunk) ab. Den Zwei kann man dann auschecken, bearbeiten und wieder commiten. Die Veränderungen beeinflussen dann die Quelltexte der Hauptentwicklungslinie nicht. Wenn er die gleiche Fehlerbehebung braucht, kann man die beiden Verzweige "mergen" - ein "merge" ist also nichts weiter als ein etwas ungewöhnliches Update, welches wie die Einspielung eines Patches abläuft. Ein "merge" endet in einem Konflikt, wenn die Veränderung beim Nebenzweig auf einen Quelltext stösst, der seither stark verändert wurde.

1. Erzeugung eines Zweiges basierend auf einem alten Veröffentlichungsstand

Alte Markierung auschecken in neues Verzeichnis (-d) und mit der -b Option neu markieren:

cd ..
cvs -q checkout -d projekt_alter_release -r Release-2004_05_01 projekt
cd projekt_alter_release
cvs -q tag -b Release-2004_05_01-buxfixes-branch

Das Archiv hat nun einen Zweig, die Arbeitskopie aber noch nicht!

2. Die Arbeitskopie zu einem Zweig machen

a) cvs checkout -d arbeitsverzeichnis -r Release-2004_05_01-bugfixes-branch projekt
b) cvs update -r Release-2004_05_01-bugfixes-branch

Das Resultat ist das gleiche.

a) wenn das aktuelle Arbeitsverzeichnis Veränderungen hat, die noch nicht durch commit abgeschickt wurden
b) hier würde cvs sonst versuchen, die Änderungen in die Arbeitskopie einfliessen zu lassen --> unreiner Zweig

3. Check

cvs -q status hello.c

4. Veränderungen machen und updaten

cvs -q update

5. Revisionsnummern checken (Zweignummer+Ziffer)

Achtung: Die Revisionsnummern haben nun 4 Ziffern anstatt 2

cvs -q status

CVS erzeugt also z.B. bei 5 Daeien 5 Verzweigungen mit dem Namen Release-2004_05_01-buxfixes-branch

Beispiel:

hello.c hat beim Erstellen der Verzweigung die Revisionsnummer 1.5
die Verzweigung (!) bekommt die Nummer 1.5.2, alle weiteren hello.c Dateien die Nummer 1.5.2.x

Achtung: die 1. Revisionsnummer in einem Zweiges ist identisch mit derjenigen in der Hauptentwicklungslinie

Aufgrund dieser Nummerierungsweise ist der Markierungsname das einzige Mittel, um Dateien eines gleichen Zweiges zu identifizieren.

Achtung: Dateien in einem Zweig sollten nie anhand ihrer Revisionsnummer geupdatet werden.

Verzweigte Dateien und nicht verzweigte Dateien sollte man also nie mischen!

Zweige können sich übrigens beliebig oft wieder verzweigen.

6. Zweig und Stamm verschmelzen (Veränderungen mergen)

cvs -q update -A
cvs -q diff -c -r Release-2004_05_01-bugfixes-branch
cvs -q update -j Release-2004_05_01-bugfixes-branch
cvs -q commit -m "merge mit der Verzweigung Release-2004_05_01-bugfixes-branch"

Wenn Konflikte auftreten, muss man diese normal auflösen, wie oben beschrieben!

Achtung: Jetzt ist eine Neumarkierung des Zweiges zu empfehlen, siehe unten!

cvs -q tag Release-2004_05_01-bugfixes-branch-fix-1

7. Mehrfache Verschmelzungen

Manchmal wird ein Zweit weiterentwickelt, obwohl die Hauptentwicklungslinie schon damit verschmolzen wurde.

Wenn man es gleich wie im Schritt 6 macht, wird ein Konflikt angezeigt, auch wenn keiner existiert. Darum sollte man nur jene Veränderungen mergen, welche nach dem Zeitpunkt der letzten Veränderung im Nebenzweig noch gemacht wurden.

cvs -q update -j "Release-2004_05-01-bugfixes-branch:2 days ago" -j Release-2004_05-01-bugfixes-branch

Da dies kompliziert ist, sollte man den Zweig nach jedem merge wieder neu markieren!

Wurde dies gemacht, so wie oben beschrieben, geschieht der erneute "merge" so:

cvs -q update -j Release-2004_05_01-bugfixes-branch-fix-1 -j Release-2004_05_01-bugfixes-branch

So muss man sich nicht daran erinnern, wann denn genau die letzte Verschmelzung stattgefunden hat!

8. Eine Markierung oder einen Zweig ohne Arbeitskopie erstellen

cvs tag -b Release-2004_05_01-bugfixes-branch

erstellte in obigem Beispiel einen Zweig, der bei Release-2004_05_01 verwurzelt ist. Da wir aber die Markierung der Veröffentlichung kannten, hätten wir es auch so machen können:

cvs rtag -b -r Release-2004_05_01 Release-2004_05_01-bugfixes-branch-fix-1 projekt

man gibt also die Wurzel der Verzweigung an - so braucht man keine Arbeitskopie, um einen Zweig zu erstellen. Die CVSROOT Umgebungsvariable muss dabei natürlich auf das Archiv verweisen, sonst muss man zusätzlich noch die -d Option verwenden.

DIE ADMINISTRATOR-KOMMANDOS IN EINER UNIX UMGEBUNG

Wie setze ich einen CVS Server auf? (sehr rudimentär)

A. INSTALLATION

Wenn ein RPM Paket vorhanden ist, dieses in /usr/src/packages/RPMS/ ablegen. Dann folgendes:

cd /usr/src/packages/RPMS/
rpm -Uhv cvs*.rpm

Alternativ: Die source selbst kompilieren!

Download unter:

ftp://ftp.gnu.org/gnu
ftp://ftp.cvshome.org/pub

hier wäre z.B. cvs-1.11 stabil, cvs-1.10.7 hingegen eine Interimsversion.

Auf dem GNU Server werden wohl nur die stabilen Versionen angeboten!

Zuerst also CVS ziehen, dann folgendes:

tar xvf cvs-1.11.tar.gz
cd cvs-1.11
./configure
make
make install

so geht die binary nach /usr/local/bin/cvs

(will man sie woanders hinpacken, dann z.B. ./configure --prefix/usr)

Ich empfehle ./configure --prefix=/usr/local wo die Dateien standardmässig sowieso hingehen!

TIPP: Anstatt "make install" den Befehl "checkinstall" ausführen!

(das Paket "checkinstall" muss dazu installiert sein)

so wird ein RPM gebastelt, welches man sich wie folgt installieren kann:

cd /usr/src/packages/RPMS/
rpm -Uhv cvs*.rpm

dadurch wird eine eventuelle spätere Entfernung erheblich vereinfacht, weil das ganze korrekt in die RPM Datenbank eingebunden wird. Selbstkompilierte Programme sind da nämlich normalerweise nicht drin, was im Extremfall im Abhängigkeitschaos enden kann.

B. KONFIGURATION

1. CVS Archiv eröffnen

cvs -d /usr/local/name init

zum Beispiel:

cvs -d /usr/local/radio init

das gucken wir uns gleich mal an:

ls -ld /usr/local/radio/
cd /usr/local/radio/
ls
cd CVSROOT/
ls

2. Neue Unix-Gruppe erzeugen

Eine neue Unix-Gruppe "cvs" erzeugen und dort alle Benutzer reinschreiben, welche das Archiv benutzen dürfen.

zum Beispiel so:

cvs:*:105:peter,paul,anonymous

in die /etc/group einfügen!

3. Zugriffsrechte auf Unix-Ebene einrichten

cd /usr/local/radio
chgrp -R cvs .
chmod ug+rwx . CVSROOT

ACHTUNG: die Punkte genau so schreiben wie oben!

So erlaubt man allen Angehörigen der Unix-Gruppe "cvs" imports, checkouts, updates und commits. Das Archiv ist für sie über :ext: erreichbar, sofern sie rsh/ssh Zugriff haben. Komisch ist auf den ersten Blick, dass wir dem Benutzer "anonymous" Schreibrechte auf den Server geben. das geht aber okay, weil wir für ihn später mit anderen Mitteln noch die "Nur-Lese" Restriktion einbauen werden.

4. Konfiguration von (x)inetd

Wenn jemand den CVS Server kontaktiert, wählt er sich über den CVS Standard port 2401 ein. Den könnte man natürlich auch ändern, was aber im Normalfall nicht notwendig ist. Der CVS Server wartet übrigens nicht auf Verbindungen zu diesem port, er läuft also nicht rund um die Uhr. Stattdessen horcht der Unix Internet daemon inetd ständig an dem port und startet automatisch den CVS Dienst, sobald eine Verbindung reinkommt.

Die config files von inetd sind /etc/services und /etc/inetd.conf - diese müssen wir also ändern!

/etc/services setzt die Portnummer in Dienstamen um
/etc/inetd.conf teilt inetd mit, was für einen bestimmten Dienstnamen zu tun ist

also ergänzen wir in der /etc/services folgende Zeilen, falls sie noch nicht drin sind:

cvspserver 2401/tcp # cvspserver
cvspserver 2401/udp # cvspserver

falls der server nicht inetd, sondern xinetd verwendet, folgendes ändern:

/etc/xinetd.d/cvs

# CVS pserver (remote acces to your CVS repositories)
# Please read the section on security and passwords in the CVS manual,
# before you enable this.
# default: off

service cvspserver
{
disable = yes
socket_type = stream
protocol = tcp
wait = no
user = root
server = /usr/bin/cvs
server_args = -f --allow-root=/home/cvsroot pserver
}

cvspserver stream tcp nowait root /usr/bin/cvs --allow-root=/usr/local/radio pserver

ACHTUNG: Verwendet der Server tcp wrapper? Wenn ja, sieht es so aus:

cvspserver stream tcp nowait root /usr/sbin/tcpd /usr/bin/cvs --allow-root=/usr/local/radio pserver

nun muss man entweder rebooten oder noch besser einfach den (x)inetd daemon neu starten!

5. Passwortauthentisierung einrichten

okay, Verbindungen sind nun erlaubt, aber es fehlt noch an Restriktionen.

nun wechselt man ins CVSROOT und erzeugt dort die Datei "passwd" - eventuell existiert sie sogar schon.

sie könnte zum Beispiel so aussehen:

paul:rKa5jzULzmhOo
peter:tGX1fS8sun6rY:pete
anonymous:XR4EZcEs0szik

Syntax: <benutzername>:<verschlüsseltes passwort>:<optionaler system benutername>

Grundsätzlich läuft eine CVS Sitzung unter dem <benutzername> - ihn haben wir oben schon in die Gruppe CVS eingetragen. Ist jedoch ein <optionaler system benutername> angegeben, wird der Transfer auf diese entsprechende Unix-Gruppe abgebildet und läuft mit auch mit ihren Rechten. Das Passwort wird dabei mit denselben Algorithmen wie die Standard Unix-Systempasswörter in /etc/passwd verschlüsselt. Darum sollte es auf jeden Fall ein anderes sein!

Doch wie findet man die verschlüsselte Version eine Passwortes raus?

Wir verwenden dazu folgendes Perl Skript

#! /usr/bin/perl

srand (time());
my $randletter= "(int (rand (26)) + (int (rand (1) + .5) % 2 ? 65 : 97))";
my $salt = sprintf ("%c%c", eval $randletter, eval $randletter);
my $plaintext = shift;
my $crypttext = crypt ($plaintext, $salt);

print "${crypttext}\n";

dieses speichert man in /usr/local/bin als cryptout.pl und macht es wie folgt ausführbar:

chmod a+x cryptout.pl

folgendes:

./cryptout.pl super genial

gibt zum Beispiel die Ausgabe:

Faud2nH6BDBHw

Den wert "Faud2nH6BDBHw" (bzw. die Ausgabe, der Passwörter, die man vergeben will) kopiert man nun in die CVSROOT/passwd rein und zwar wie folgt:

johannes:Faud2nH6BDBHw

etc.

Johannes kann sich also von jetzt an mit "super genial" einloggen:

zum Beispiel so:

cvs -d :pserver:johannes@dachboden-wg.de:/usr/local/radio super genial

Wenn jemand versucht, sich mit einem Benutzernamen und Passwort zu identifizieren, welche nicht in CVSROOT/passwd hinterlegt sind, prüft cvs automatisch, ob der Benutzername vielleicht in /etc/passwd hinterlegt ist. Wenn ja, kann sich der Benutzer auch so einloggen.

Warum? Es erleichtert dem Admin die Arbeit, weil er so separate CVSROOT/passwd Einträge gar nicht erst machen muss, wenn der Benutzer schon in /etc/passwd hinterlegt ist. Das ist aber sicherheitstechnisch schlecht (das Passwort wird im Klartext übertragen und kann "gesnifft" werden) - darum lässt sich dies abschalten, was man auf jeden Fall auch tun sollte.

6. Beschränkung auf ein Projekt

Alle user, die in CVSROOT/passwd eingetragen sind, haben per default Zugriffsrechte auf sämtliche CVS Projekte, was natürlich nicht klever ist. Darum erzeugen wir projektspezifische Benutzerkennungen und Gruppen, zum Beispiel so;

/etc/passwd editieren:

cvs-radio:*:600:600:public CVS Account for Project radio:/usr/bin/cvs:/bin/false
cvs-forum:*:601:601:public CVS Account for Project forum:/usr/bin/cvs:/bin/false

in /etc/group demnach folgendes:

cvs-radio:*:600:cvs-radio
cvs-forum:*:601:cvs-forum

und in CVSROOT/passwd z.b. folgendes:

paul:rKa5jzULzmhOo:cvs-radio
peter:tGX1fS8sun6rY:cvs-radio
claudia:SzDlyzk2EJznc:cvs-forum

so bildet man die CVS Benutzernamen auf die Systembenutzerkennungen cvs-radio und cvs-forum ab.

7. "Nur-Lese" Zugriff für gewisse User einrichten

bisher erteilten wir vollen Zugriff auf einzelne Archive für einzelne Benutzer.

in vielen Fällen kann aber für gewisse Benutzer eine "Nur-Lese" Einschränkung sinnvoll sein!

dazu erstellt man folgende zwei dateien:

CVSROOT/readers (Benutzerliste für Lesezugriff)
CVSROOT/writers (Benutzerliste für Lese- und Schreibzugriff)

die readers hat z.B. folgenden Inhalt:

anonymous
claudia

das Format ist einfach, ein Benutzer pro Zeile.

ACHTUNG: Die Namen beziehen sich nur auf CVS Benutzernamen und nicht auf die System-Benutzernamen!

so sieht ein typischer "Nur-Lese" Zugriff für einen anonymen user also in etwa aus:

in CVSROOT/passwd

anonymous:rKa5jzULzmhOo

in /etc/passwd

anonymous:!:1729:105:Anonymous CVS User:/usr/local/radio:/bin/false

in CVSROOT/readers

anonymous

die entsprechenden einträge in /etc/services und /etc/inetd.conf

(wie oben beschrieben)

nun läuft der Server und die Basis-Konfiguration ist abgeschlossen!
 
OP
S

shattered

Member
So, fertig! :D

Da CVS für mich selbst noch Neuland ist, könnte die Einführung noch ganz kleine Fehler enthalten, für Anregungen und Verbesserungsvorschläge bin ich also immer offen! 8)
 
Oben