poprawne wywołanie rsync w bash

Bash, C, C++, Java, PHP, Ruby, GTK, Qt i wiele innych - wszystko tutaj.
lis3k
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 08 cze 2008, 19:42
Płeć: Mężczyzna
Wersja Ubuntu: 12.04
Środowisko graficzne: Xfce
Architektura: x86_64

poprawne wywołanie rsync w bash

Post autor: lis3k »

Witam,
piszę sobie prosty skrypt, który będzie dbał o robienie kopii zapasowych folderów, do których ścieżki będą zapisane w pewnym pliku. I właśnie tu mam problem, jak poprawnie podać listę plików do rsync, bo on chyba nie trawi apostrofów ani cudzysłowów...
RSYNC dla rsync -avr '/home/pawel/Dokumenty/*' '/home/pawel/backup' zwraca:
rsync: link_stat "/home/pawel/Dokumenty/*" failed: No such file or directory (2)
ale gdy podam źródło bez apostrofów-zadziała prawidłowo

Funkcja w której cała akcja się dzieje:

Kod: Zaznacz cały

kopiuj() {
	cat '.backup-list' | while read directoryPath
	do 
		rsync -avr "$directoryPath" '/home/pawel/backup'
	done 
}
Skrypt wczytuje po kolei linie z pliku '.backup-list' i wrzuca je do $directoryPath.
Jeśli ta zmienna objęta jest cudzysłowami (jak pokazano wyżej) nie chce się kopiować nic,
jeśli zmienna będzie "goła" bez apostrofów/cudzysłowów, to program będzie miał problemy ze ścieżkami do folderów, które zawierają spacje...
Np. dla listy:
/home/pawel/Dokumenty/*
/home/pawel/ppp/*
/home/pawel/spacja spacja/*
wyrośnie:

Kod: Zaznacz cały

sending incremental file list
sent 8813 bytes  received 29 bytes  17684.00 bytes/sec
total size is 28111854  speedup is 3179.35
(^^ to dla /Dokumenty/ )
sending incremental file list
sent 131 bytes  received 13 bytes  288.00 bytes/sec
total size is 1969  speedup is 13.67
(^^ to dla /ppp/ )

(tu się zaczyna cały problem ze ścieżką: /home/pawel/spacja spacja/* )
sending incremental file list
rsync: link_stat "/home/pawel/spacja" failed: No such file or directory (2)
rsync: change_dir "/home/pawel//spacja" failed: No such file or directory (2)
sent 12 bytes  received 12 bytes  48.00 bytes/sec
total size is 0  speedup is 0.00
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1070) [sender=3.0.9]
Dla zainteresowanych-cały skrypcik. Nie ma sensu robić backupu w folderze obok na tym samym dysku, ale ostatecznie to będzie inny dysk. Na innym komputerze ;)

Kod: Zaznacz cały

#!/bin/sh
kopiuj() {
	cat '.backup-list' | while read directoryPath
	do 
		rsync -avr $directoryPath '/home/pawel/backup'
	done 
}

if [ "$1" = "start" ]
	then
	rm '/home/pawel/.backup-lock'
	touch '/home/pawel/.backup-enabled'
	echo 'backup odblokowany'
fi

if [ -e '/home/pawel/.backup-enabled' ]
	then
	if [ -e '/home/pawel/.backup-lock' ]
		then
		echo 'kopiowanie już rozpoczęte...'
	else
		touch '/home/pawel/.backup-lock'
		echo 'rozpoczęcie kopiowania...'
		kopiuj
		rm '/home/pawel/.backup-lock'
		echo 'zakończenie kopiowania'
	fi
fi

if [ "$1" = "stop" ]
	then
	rm '/home/pawel/.backup-enabled'
	while [ -e '/home/pawel/.backup-lock' ] ; do
		sleep 1
		echo 'czekam na zakończenie poprzedniego kopiowania'
	done
	kopiuj
	echo 'ostatni backup wykonany'
fi
Najpierw włączamy robienie backupa:
./.backup-rsync start
(tak się plik u mnie nazywa)
potem cyklicznie
./.backup-rsync
a na koniec
./.backup-rsync stop
(w celu ostatecznego skopiowania wszystkiego przed wyłączeniem komputera-jeszcze nie wiem gdzie to wsadzić, żeby zadziałało w czasie wylogowywania, i najlepiej opóźniło wylogowanie aż się nie skopiuje... pomysły?? ;) )
norvoles
Przebojowy Jelonek
Przebojowy Jelonek
Posty: 1113
Rejestracja: 04 sty 2008, 20:58
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: Inne
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: norvoles »

Rozumiem, że to:

Kod: Zaznacz cały

/home/pawel/Dokumenty/*
/home/pawel/ppp/*
/home/pawel/spacja spacja/*
jest zawartość pliku .backup-list?

Jeśli tak, to po prostu usuń gwiazdki i zostaw cudzysłowy :P
Rsync z opcją -r kopiuje katalogi rekursywnie.
(w celu ostatecznego skopiowania wszystkiego przed wyłączeniem komputera-jeszcze nie wiem gdzie to wsadzić, żeby zadziałało w czasie wylogowywania, i najlepiej opóźniło wylogowanie aż się nie skopiuje... pomysły?? ;) )
Przy wylogowaniu (tylko) powinno zadziać to: http://www.cyberciti.biz/faq/linux-unix ... u-log-out/
A przy wyłączeniu to: https://synapse.wordpress.com/2007/03/2 ... -in-linux/ powinno zadziałać pod Ubu.
Słowo-klucz: runlevel 6
lis3k
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 08 cze 2008, 19:42
Płeć: Mężczyzna
Wersja Ubuntu: 12.04
Środowisko graficzne: Xfce
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: lis3k »

Te 3 ścieżki to właśnie ten plik .backup-list

Bez gwiazdek i w cudzysłowie działa świetnie, dzięki.
Dziękuję też za linki do stron, przydadzą się niedługo.

Ale aktualnie mam problem jeszcze z czymś...
Jeśli wszystkie katalogi z listy skopiuję do jednego, to się zrobi bajzel, więc pomyślałem żeby zrobić taki plik .backup-list
Dokumenty>/home/pawel/Dokumenty/
PPP>/home/pawel/ppp/
Spacje>/home/pawel/spacja spacja/
Pierwsza część to nazwa folderu na serwerze kopii (pierwszy to np. /home/pawel/backup/Dokumenty/), potem separator ">" a dalej katalog do skopiowania.
Czyli plan jest taki: znaleźć ">", wyciąć część od początku do ">", wyciąć część od ">" do końca.
Na chwilę obecną funkcja wygląda tak:

Kod: Zaznacz cały

kopiuj() {
	cat '.backup-list' | while read directoryPath
	do 
		separator=`expr index "$directoryPath" ">"`
		zrodlo= ${directoryPath:$separator}
		nazwa= ${directorPath:0:$separator}
		cel= "/home/pawel/backup/$nazwa"
		rsync -avr "$zrodlo" "$cel"
		done 
}
domyślam się że błąd leży gdzieś w składni, ale naprawdę wiele mi zajęło samodzielne wykumanie (w żadnym kursie nie zwrócili szczególnie na `ten` przypadek uwagi), że przez `expr... nie ma być spacji ;)
Na chwilę obecną mam:
./.backup-rsync: 6: ./.backup-rsync: Bad substitution
Linia 6 to ta: zrodlo= ${directoryPath:$separator}
norvoles
Przebojowy Jelonek
Przebojowy Jelonek
Posty: 1113
Rejestracja: 04 sty 2008, 20:58
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: Inne
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: norvoles »

Ja do takich rzeczy używam cut w taki sposób:

Kod: Zaznacz cały

kopiuj() {
   cat '~/.backup-list' | while read directoryPath
   do
      separator=">"
      zrodlo=$(echo "$directoryPath" | cut -d'>' -f2)
      nazwa=$(echo "$directoryPath" | cut -d'>' -f1)
      cel= "/home/pawel/backup/$nazwa"
      rsync -avr "$zrodlo" "$cel"
      done
}
Nawet nie wiedziałem, ze można to tak zrobić jak napisałeś :D
Na chwilę obecną mam:
./.backup-rsync: 6: ./.backup-rsync: Bad substitution
Linia 6 to ta: zrodlo= ${directoryPath:$separator}
Po znaku = nie może być spacji.
lis3k
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 08 cze 2008, 19:42
Płeć: Mężczyzna
Wersja Ubuntu: 12.04
Środowisko graficzne: Xfce
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: lis3k »

Ok, dzięki jeszcze raz ;)
Aktualna wersja skryptu:

Kod: Zaznacz cały

#!/bin/sh
kopiuj() {
	cat '.backup-list' | while read directoryPath
	do 
		separator=">"
		zrodlo=$(echo "$directoryPath" | cut -d'>' -f2)
		nazwa=$(echo "$directoryPath" | cut -d'>' -f1)
		cel="/home/pawel/backup/$nazwa"
		rsync -avr "$zrodlo" "$cel"
	done 
}

if [ "$1" = "start" ]
	then
	rm '/home/pawel/.backup-lock'
	touch '/home/pawel/.backup-enabled'
	echo 'backup odblokowany'
elif [ "$1" = "stop" ]
	then
	rm '/home/pawel/.backup-enabled'
	if [ -e '/home/pawel/.backup-lock' ]
		then
		echo 'czekam na zakończenie poprzedniego kopiowania'
	fi
	while [ -e '/home/pawel/.backup-lock' ] ; do
		sleep 1
		echo '.'
	done
	kopiuj
	echo 'ostatni backup wykonany'
else
	if [ -e '/home/pawel/.backup-enabled' ]
		then
		if [ -e '/home/pawel/.backup-lock' ]
			then
			echo 'kopiowanie już rozpoczęte...'
		else
			touch '/home/pawel/.backup-lock'
			echo 'rozpoczęcie kopiowania...'
			kopiuj
			rm '/home/pawel/.backup-lock'
			echo 'zakończenie kopiowania'
		fi
	fi
fi
norvoles, skąd właściwie uczyłeś się basha? Bo ja to tak kojarzę jak działają pętle, ify... z innych języków, a basha to na bieżąco, od bloga do bloga szukam gotowców i coś z tego składam...

Ostatecznie dorzucę coś graficznego do skryptu żeby ładnie wyglądało (może zrobię 2 wersje, zenity i kdialog). Kiedy już skrypt uznam za skończony ;)
Mały 1
Zakręcona Traszka
Zakręcona Traszka
Posty: 548
Rejestracja: 24 sty 2008, 15:55
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: LXDE
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: Mały 1 »

Jak plik będzie miał taką nazwę to skrypt zadziała?

Kod: Zaznacz cały

`[~!($%^_&*){.}\___"`]`1.jpg
lis3k
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 08 cze 2008, 19:42
Płeć: Mężczyzna
Wersja Ubuntu: 12.04
Środowisko graficzne: Xfce
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: lis3k »

Jedyny warunek, to żeby w pliku .backup-list nie pojawił się ">" wcześniej niż ten właściwy separator, który oddziela nazwę folderu na serwerze od ścieżki do folderu do skopiowania. W każdym innym przypadku skrypt zadziała prawidłowo (no bo dla kompa to jest bez różnicy generalnie, literki, cyferki, procenciki-jeden grzyb, tylko na ">" musi uważać).

A w ogóle to pliki nazywaj sobie jak chcesz, a jak coś nie zadziała, to do twórców rsync'a zażalenie proszę słać ;) Mój skrypt tylko foldery mu wskazuje, jak coś w tej kwestii nie zadziała a faktycznie będzie Ci to niezbędne, napisz tutaj albo na pw, pomyślimy.
Mały 1
Zakręcona Traszka
Zakręcona Traszka
Posty: 548
Rejestracja: 24 sty 2008, 15:55
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: LXDE
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: Mały 1 »

Co się stanie z folderami i plikami o takich samych nazwach?
lis3k
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 08 cze 2008, 19:42
Płeć: Mężczyzna
Wersja Ubuntu: 12.04
Środowisko graficzne: Xfce
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: lis3k »

jeśli w folderze źródłowym będą nowsze niż w docelowym, zastąpią je.
Przyjrzyj się skryptowi, to zobaczysz że on tylko ogarnia listę folderów do zarchiwizowania, całą resztą zajmuje się rsync-ostatecznie to on odpowiada za to co się stanie z tymi plikami, więc w takich sprawach to nie pytaj tu, tylko zapytaj swojego terminala ;) rsync --help

EDIT:
właściwie to możesz go sobie poustawiać jak chcesz, w pomocy rsync'a masz przecież masę opcji.
Mały 1
Zakręcona Traszka
Zakręcona Traszka
Posty: 548
Rejestracja: 24 sty 2008, 15:55
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: LXDE
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: Mały 1 »

Jeżeli chodzi tylko o kopiowanie plików to można prościej:

Kod: Zaznacz cały

ls -l | awk '/^-/{system(" rsync -avz `pwd`/\047" $8 "\047 `pwd`/kopia ")}'
Oczywiście, że ścieżkę należy zmienić według własnych potrzeb.

EDIT:

Jeżeli chesz, aby awk czytał ścieżkę z pliku o nazwie 'backup' to robisz tak:
Zawartość Twojego pliku 'backup':

Kod: Zaznacz cały

/home/pawel/Dokumenty
/home/pawel/ppp
/home/pawel/spacja spacja
Teraz wystarczy takie polecenie:

Kod: Zaznacz cały

mkdir kopia | cat backup | awk '{system(" rsync -avr \047" $0 "\047 `pwd`/kopia ")}'
lis3k
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 08 cze 2008, 19:42
Płeć: Mężczyzna
Wersja Ubuntu: 12.04
Środowisko graficzne: Xfce
Architektura: x86_64

Re: poprawne wywołanie rsync w bash

Post autor: lis3k »

wiem, że to się da zrobić na taki i sto innych sposobów, ale wymyślenie takiego najszybciej mi przyszło ;) poza tym, chcę w przyszłości (już w gnome, na razie mam xfce) użyć w tym zenity, żeby coś niecoś powiedział o tym czy się udało czy nie... kto wie, czy nie najdzie mnie ochota na dodanie wake-on-lan jeśli akurat serwerek śpi... No i jeszcze za słaby z basha jestem żeby tak ostro zagnieżdżać :P
ODPOWIEDZ

Wróć do „Programowanie”

Kto jest online

Użytkownicy przeglądający to forum: Amazon [Bot] i 9 gości