ubuntuusers.de

Symbolischen Link überprüfen und ggf. ersetzen.

Status: Ungelöst | Ubuntu-Version: Server 8.04 (Hardy Heron)
Antworten |

Christofer

Avatar von Christofer

Anmeldungsdatum:
2. Februar 2007

Beiträge: 185

Hallo Community,

ich bin zur Zeit dabei ein Skript zu schreiben das mir automatische Updates von mehreren Typo3-Installationen ermöglicht. Es ist mein erstes wirklich eigenständiges Shell-Skript ☺ Das Skript lädt bisher schon mal die aktuelle Typo3-Version herunter, entpackt sie, setzt die Rechte und löscht die alte Version. Nun möchte ich in jedem Verzeichnis nach einem symbolischen Link suchen, den Verweis auf die Datei prüfen und bei Übereinstimmung diesen Link ersetzen. Wie mache ich das? Ich vermute mal das geht z.B. mit dem Befehl find. Kann mir einer hier einen Tipp geben wie das aussehen muss?

Danke schon mal für Euer Wissen und Eure Zeit!

theinlein

Anmeldungsdatum:
29. Dezember 2007

Beiträge: 1279

symbolische Links sucht man mit

find verzeichnis   -type l   ...

aber was willst du machen, wenn find so einen Link gefunden hat?

Was heißt 'Übereinstimmung' bzw 'Verweis prüfen' in deinem Post? Ob eine Datei existiert, auf die der Link zeigt? Muss die einen bestimmten namen haben ? ...?

Christofer

(Themenstarter)
Avatar von Christofer

Anmeldungsdatum:
2. Februar 2007

Beiträge: 185

@theinlein danke, ich bekomme mit

# find /var/www -type l -name typo3_src

/var/www/verz1/typo3_src
/var/www/verz2/typo3_src
/var/www/verz2/typo3_src
...

alle Links aufgelistet. Jetzt muss ich nur noch den Link prüfen und ersetzen. So sieht der Link aus:

typo3_src -> ../typo3_src-4.2.16

das Linkziel soll geändert werden in:

typo3_src -> ../typo3_src-4.2.17

wobei ich die beiden Versionsnummern schon in Variablen gespeichert habe, so das ich das Linkziel mit:

$NEWLINK=../typo3_src-$NEWVERSION

ändern könnte. Aber wie kann ich das Ziel des Links prüfen und dann ändern? Da verschiedene Versionszweige vorhanden sind muss er erst die Version prüfen bevor er sie ersetzt. Das Vorhandensein der Datei braucht nicht geprüft werden, sondern nur die Versionsnummer im Link selber.

xabbuh Team-Icon

Anmeldungsdatum:
25. Mai 2006

Beiträge: 6411

Mit readlink kannst du dir ausgeben lassen, welches Ziel ein Link hat.

Christofer

(Themenstarter)
Avatar von Christofer

Anmeldungsdatum:
2. Februar 2007

Beiträge: 185

@xabbuh, ah super, das ist das was ich gesucht habe. Was mir jetzt fehlt ist die Möglichkeit daraus eine Schleife zu machen.

Find liefert mir die Liste:

# find /var/www -type l -name typo3_src

/var/www/verz1/typo3_src
/var/www/verz2/typo3_src
/var/www/verz2/typo3_src
...

readlink den Inhalt:

#readlink /var/verz1/typo3_src 
../typo3_src-4.2.16

Wie packe ich das nun in eine Schleife die Verzeichnis für Verzeichnis durchgeht und mit readlink den Inhalt ausgibt? Ich denke den Rest, die Prüfung des Links und das neu setzen sollte ich hin bekommen.

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Bash (that is, not posix):

1
2
3
4
5
6
#!/bin/bash
while read -r line
do
    target=$(readlink "$line")
    echo "$line" zeigt auf "$target"
done < <(find /var/......)

theinlein

Anmeldungsdatum:
29. Dezember 2007

Beiträge: 1279

... was auch geht ...

find /var/www -type l -name typo3_src  -exec readlink  \{\} \;

d.h. man kann dem find für jeden "Fund" einen oder mehrere Commands/Script mitgeben - mit der Option -exec. Die 2 geschweiften Klammern sind der Platzhalter für das soeben Gefundene. Die Backslashes sind dafür da, dass die Klamern nicht von der Shell, sondern erst im 'find' behandelt werden, gleich so mit dem Semikolon - das braucht das find.

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

… und was auch noch geht, wäre sowas:

1
2
3
4
5
6
7
8
9
#!/bin/bash
while true
do
	read -d '' -r path || break
	read -d '' -r link

	echo "$path --> $link"

done < <(find -type l -printf '%p\0%l\0')

%p“ ist der gewöhnliche Pfad, den find normalerweise ausspuckt, und „%l“ dann das Ziel des jeweiligen Links. Beide Sachen sauber mit Nullbytes getrennt und dementsprechend eingelesen („-d ''“). So sparst du dir halt den extra Prozess für jeden aufzulösenden Link.

Aber wahrscheinlich ist das eh schon overpowered. 😉

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Vorsicht mit der while read -r line - Version !

Abgesehen von der Notwendigkeit des sauberen "Quotens" tickt diese Variante aus, wenn ein Zeilenvorschub im Pfad vorkommt:

mkdir '/var/www/böse
Falle
!/'
touch '/var/www/böse
Falle
!/typo3_src'

- probier es mal aus ...

Das Problem ist erledigt, wenn man entweder find ... -print0 verwendet, und die Null-terminierten Strings dann weiter verarbeitet.
(aber das bekomme ich mit read nicht hin) edit: Vain, das war der "Missing Link" !
also:

#!/bin/bash

find /var/www -type l -name typo3_src  -print0  |  while read -d '' -r line
do
    target="$(readlink -e "$line")"
    echo "$line" zeigt auf "$target"
done

- oder wenn man es über -exec erledigt:

#!/bin/bash

find /var/www -type l -name typo3_src  -exec bash -c "echo -n '{}  zeigt auf  ' ; readlink -e '{}'" \;

so wie es theinlein gemacht hat - und das funktioniert eben auch mit mehreren Befehlen.

track

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Au, ja, mein Erstes fliegt auseinander, wenn Newlines drin sind.

Sauber gequotet ist das aber. Bei einer Zuweisung kannst du dir die Quotes in dem Fall schenken. Kann dir die passende Stelle aus der „heiligen Schrift“ (aka Bash Manual 😉) gerade nicht nennen, aber probier’ mal:

$ foo=$(curl -s ubuntuusers.de)
$ echo "$foo" | less 

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Nee Vain, ein Pärchen "Quotes" hattest Du doch vergessen:

    target="$(readlink "$line")"

edit: Du hast Recht, die braucht man nicht ! - verblüfft mich, stimmt aber.
Das ist anscheinend das selbe wie {} bei find, das nimmt ja auch alle Sonderzeichen mit, ohne quoten.
Danke, Vain !

LG,

track

Christofer

(Themenstarter)
Avatar von Christofer

Anmeldungsdatum:
2. Februar 2007

Beiträge: 185

Hallo Leute vielen Dank für Eure Hilfe. Hiermit präsentiere ich mein erstes Shell-Skript. Es ist natürlich open Source. Es funktioniert soweit. Ich werde nur nochmal die Ausgaben der Shell überarbeiten und später das Ganze so anpassen das es über PHP gestartet werden kann. Dafür wäre es sehr schön, wenn die Statusmelungen in PHP ausgegeben werden könnten. Die einzige Möglichkeit die mir einfällt ist, das man die Ausgaben der Shell in eine Datei umleitet und diese über PHP ausliest, oder gibt es da noch andere Möglichkeiten?

#!/bin/bash

# Konfiguration
WORKDIR=/var/www
T3URL=http://downloads.sourceforge.net/typo3/

# Wechsle in das Arbeitsverzeichnis
echo cd $WORKDIR

echo "Aktualisierung von Typo 3"
echo "========================="
echo ""
read -p "Welche alte Version von Typo3 soll ersetzt werden (z.B. 4.4.4): " OLDT3VERSION
echo ""
read -p "Durch welche neue Version soll diese ersetzt werden (z.B. 4.4.5): " T3VERSION

# Datei- und Verzeichnisnamen erstellen
T3NAME=typo3_src-$T3VERSION.tar.gz 
T3DIR=typo3_src-$T3VERSION

# Hole die neue Typo3-Version vom Server, entpacke sie und setze die Rechte neu
wget $T3URL$T3NAME
tar zxvf $T3NAME
chown -R www-data:www-data $WORKDIR/$T3DIR

echo ""
echo "Die symbolischen Links werden neu gesetzt!"
echo ""

find $WORKDIR -type l -name typo3_src | while read T3LINK; do

	CURRENTVERSION=$(readlink $T3LINK | cut -d"-" -f2)

	if [ "$CURRENTVERSION" == "$OLDT3VERSION" ];then

		T3LINKNEW=../typo3_src-$T3VERSION

		rm $T3LINK && ln -s $T3LINKNEW $T3LINK
		chown -R www-data:www-data $T3LINK		
		T3SYSTEM=$(echo $T3LINK | cut -d"/" -f4)
		echo System: $T3SYSTEM mit der Version: $OLDT3VERSION wurde auf Version: $T3VERSION aktualisiert!

	fi
done

OLDT3NAME=typo3_src-$OLDT3VERSION
	
echo ""
echo "Das alte Typo3-Verzeichnis: $OLDT3NAME wird gelöscht!" 			
rm -r $OLDT3NAME

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Das ist doch nett ... 😉

Bei einem solltest Du aber aufpassen und Dir von vorn herein einen ganz sauberen Stil angewöhnen:

# Konfiguration
WORKDIR="/var/www"
T3URL=http://downloads.sourceforge.net/typo3/

# Wechsle in das Arbeitsverzeichnis
echo cd "$WORKDIR"

usw. ... Auch wenn das jetzt vielleicht bei Dir nichts ausmacht, solltest Du bei Pfadangaben immer sauber "quoten". Sonst kann Dein Skript im unglücklichen Fall ganz üble Dinge tun, wenn doch mal ein Leerzeichen oder Zeilenvorschub im Namen vorkommt und deshalb eine Variable auseinander fliegt.

Stell Dir z.B. mal vor was in der letzten Zeile (ohne "quotes" !) passiert, falls Deine Variable "$OLDT3NAME" jemals den Wert "~/" annimmt ...!

LG,

track

Antworten |