Egyszerre több fájl biztonságos másolása az scp parancs használatával

botond küldte be 2018. 10. 02., k – 01:23 időpontban

Tartalom

 

Bevezető

A napokban szükségem volt egy egyszerű és praktikus megoldásra, amivel egyetlen paranccsal fel tudok másolni előre meghatározott fájlokat az itthoni gépemről a szerveremre. A fájlokat ezelőtt kézzel szedegettem össze különböző könyvtárakból, majd felmásolgattam őket egyesével SSH-n keresztül. Ezután már akárhonnan könnyen hozzájuk tudok férni pl mobilról. Mivel gyakran változnak ezek a dokumentumok és bármikor meg kell tudnom nyitni őket távolról, így macerássá vált a kézi másolgatásos módszer. Így hát meguntam a banánt és gyorsan összedobtam erre egy kis shell szkriptet, amivel akár időzítetten is el tudom végezni ezeket a másolásokat egyetlen parancs lefuttatásával. A szkript egyáltalán nem nagy durranás, csak a praktikussága miatt gondoltam megosztom, hátha másnak is kapóra jön, ha egy hasonló megoldást keres.

Ebben a leírásban tehát elkészítünk egy hasonló szkriptet, de előtte megnézünk néhány példát az scp parancs működtetésére.

 

 

Az scp parancs

Aki még nem ismerné, az scp (Secure Copy) parancs segítségével tudnunk fájlokat másolni két gép között az SSH csatornán keresztül. Így az scp program a már eleve titkosított csatornán keresztül küldi vagy fogadja a paraméterben megadott fájlokat.

Lássunk is egy-egy alap példát a küldésre és a fogadásra is. Fájlokat küldeni a következő szintaxissal lehet:

scp /file/eleresi/utvonala felhasznalo@szerver:~/cel/konyvtar

Itt az első paraméterben adtuk meg a forrás fájlt, ebben az esetben a helyi gépen lévő fájlt, majd utána egy távoli gépen lévő célkönyvtárat, ami itt a megadott felhasználó home könyvtárán belül van, mivel a ~ tilde karakterrel kezdődik. Persze itt is megadhatunk abszolút elérést (pl. /home/user/), csak mivel a cél felhasználó többnyire a saját könyvtárába másolgat, így ez a rövidebb megoldás.

És most visszafelé:

scp felhasznalo@szerver:~/tavoli/forras/file/helye /helyi/cel/konyvtar

Tehát ebben nincs semmi ördöngösség, csak megfordítottuk a két paramétert, és máris a parancs futtatójának irányába másol.

Még olyat is lehet, hogy az egyik távoli szerverről másolunk át egy másik távoli szerverre fájl(okat):

scp felhasznalo@szerver1:~/tavoli/forras/file/helye felhasznalo@szerver2:~/tavoli/cel/konyvtar

A parancs futtatásakor a shell bekéri tőlünk a távoli gép jelszavát a megadott felhasználóhoz, majd elindul a másolás.

Hasznos kapcsolók

Érdemes még megemlíteni az scp parancs néhány kapcsolóját, amik jól jöhetnek bizonyos helyzetekben:

Egyedi port beállítása

Ha a szerver – amire másolni szeretnénk a fájlokat, vagy ahonnan másolni szeretnénk – nem az alapértelmezett 22-es portot használja az SSH csatlakozáshoz, hanem ettől eltérő portszámot, akkor alkalmazzuk a (nagy) -P kapcsolót a forrás és a cél fájl megadása előtt:

scp -P <egyedi portszám> <forrás fájl> <célfájl>

Másolt fájlok időbélyegének megtartása

Ha a másolás során fontos, hogy a fájlok megtartsák módosítási idejüket, akkor használjuk a (kis) -p kapcsolót:

scp -p <forrás fájl> <célfájl>

(Itt nem kell a kapcsoló után semmilyen értékadás.)

IPv4 / IPv6 kényszerítés

Amennyiben a távoli gép nem rendelkezik IPv6 címmel, akkor célszerű kényszeríteni az IPv4 használatát a -4 kapcsolóval:

scp -4 <forrás fájl> <célfájl>
Erre azért lehet szükség, mert az internetszolgáltatóknál az újabb kiépítésű végpontoknál már alapértelmezetten az IPv6-on próbálnak kommunikálni ezek a parancsok (SCP, SSH, stb). Például egy újabb DIGI hálózatról, vagy az újabb 4G-s mobilhálózatokról már nem megy fel SSH-ra, ha enélkül a kapcsoló nélkül csatlakozunk egy olyan géphez, ami csak IPv4 címmel rendelkezik.
Én már beleszaladtam ebbe, amikor az új mobilomról a 4G-s T-mobil hálózaton keresztül nem tudtam SSH-n belépni a szerverre, és nem adott semmilyen hibaüzenetet egyik oldalon sem. Az itthoni régebbi DIGI netemmel pedig simán felcsatlakozik a kapcsoló nélkül is. Kb fél napba telt, mire megtaláltam ezt a megoldást.

 

Ugyanígy a -6 kapcsolóval pedig az IPv6 használatát lehet kényszeríteni, amennyiben valakinek ilyenre van szüksége.

Rekurzív másolás

Ha egy adott könyvtárban mindent át szeretnénk másolni, az alkönyvtáraival együtt, akkor használjuk a -r kapcsolót a forrás és a cél megadása előtt:

scp -r <forrás könyvtár> <cél könyvtár>

Ilyenkor értelemszerűen könyvtárakat kell megadni, aminek a teljes tartalma átmásolásra kerül.

Egyszerre több fájl másolása

Egyszerre több fájl másolására is van lehetőség. Erre többféle módszer is van:

Csillag karakter használatával

Az alábbi példa a távoli gépen lévő felhasználó home könyvtárából átmásol minden fájlt az aktuális könyvtárba:

scp felhasznalo@szerver:/home/felhasznalo/* .

Annyiban tér el a fentebb említett rekurzív másolástól, hogy itt nem kerülnek átmásolásra a könyvtárban esetlegesen előforduló alkönyvtárak, hanem csak a fájlok.

Természetesen ez fordítva is működik:

scp * felhasznalo@szerver:/home/felhasznalo

Ez pedig felmásol minden fájlt a helyi gép aktuális könyvtárából a távoli gép felhasználójának könyvtárába.

Csak a megadott fájlok átmásolása

A következő példában a távoli gép egy könyvtárából másolunk át kiválasztott fájlokat:

scp felhasznalo@szerver:/tavoli/konyvtar/elerese/\{a,b,c\} .

Itt tehát escape-elt kapcsos zárójelek között vesszőkkel elválasztva adhatunk meg konkrét fájlneveket.

Ebben a példában pedig a helyi gépről (akár különböző könyvtárakból) másol fel megadott fájlokat a cél gép felhasználójának home könyvtárába:

scp /tmp/a.txt /home/user/b.txt /etc/valami.conf felhasznalo@szervrer:~

 

Az scp előkészítése a szkriptekhez

Már csak egy dolog maradt hátra, mielőtt nekiállhatnánk shell szkriptekben alkalmazni az scp parancsot. Mégpedig hogy kiküszöböljük a jelszó bekérését, mert az scp parancs futtatásakor megakad a programunk a jelszó bekérése miatt. Emiatt nem tudjuk automatizálni a másolási feladatainkat.

Szerencsére van erre egy kiváló megoldás. Egy korábbi leírásomban bemutattam, hogy hogyan lehet SSH-ra belépni privát és nyilvános kulcsok segítségével, hogy elkerülhessük a jelszó begépelését. 

Amennyiben szkriptekben szeretnénk használni bármilyen SSH csatornát használó parancsot (ssh, scp, rsync, stb...), akkor ezt a kulcsgenerálásos módszert mindenképpen el kell végeznünk, hogy zökkenőmentesen működhessenek a programjaink.

Ha viszont már túl vagyunk rajta, akkor léphetünk is a következő részhez..

 

 

A feladat

Mostanra tehát már ismerjük az scp parancs használatát, valamint a jelszó bekérési akadályt is elhárítottuk, így jöhet az eredeti feladatunk, mégpedig a kis másoló szkript elkészítése.

Ebben a példában néhány fájlt fogunk összeszedni a helyi gép különböző könyvtárából és azokat másoljuk fel egy távoli gép könyvtárába.

A fenti egysoros példák között is van már ilyen, így gondolhatnánk, hogy minek csavarjuk tovább a dolgot. Azonban egy szkriptben kényelmesebben lehet megoldani mindent, valamint ki lehet egészíteni olyan dolgokkal, amit éppen a feladat megkíván. És nem utolsó sorban áttekinthető lesz az egész, valamint elég csak egyetlen parancsot futtatni ezután.

Most lássunk tehát egy alapot, amiből kiindulhatunk. Legyen mondjuk a helyi linuxos szerverről néhány fájl, amit időnként fel kell másolni egy másik szerverre, ahol további feldolgozások várnak rájuk, vagy csak simán meg kell őket nyitni máshonnan:

  • /var/log/ispconfig/httpd/weboldalam.hu/error.log
  • /home/pisti/backup/site1/2018-10-01_22_00.zip
  • /var/www/weboldalam.hu/exports/statistics.xml

Direkt hosszabb fájl eléréseket találtam most ki, hogy látható legyen hogy ezekkel kényelmetlenebb lenne dolgozni egy egysoros parancsban. Nem beszélve arról, hogy a középső fájlból mondjuk óránként létrejön egy újabb, mindig az aktuális óra időbélyegével elnevezve a fájlt. Így már macerásabb és ésszerűtlen lenne ezt egy egyetlen parancssorba bezsúfolni. Helyette inkább készítünk neki egy néhány soros szkriptet, amiben kényelmesen elfér:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
# Másoló szkript...
 
# Változók:
file1="/var/log/ispconfig/httpd/weboldalam.hu/error.log"
# file2="/home/pisti/backup/site1/2018-10-01_22_00.zip"
backupdir="/home/pisti/backup/site1/"
file2=${backupdir}$(ls -tr --group-directories-first ${backupdir}*.zip | tail -n 1)
file3="/var/www/weboldalam.hu/exports/statistics.xml"
 
# Másolás:
scp -P 12345 $file1 $file2 $file3 pisti@weboldalam.hu:~/Mentesek/

Így viszont már könnyen hozzá lehet férni a fájlnevekhez, módosítani őket, stb.

A második fájlnál például bent hagytam a kommentezett fix értékadást is mintának, valamint alatta egy fordított időrenddel paraméterezett ls paranccsal lekértem a legfrissebb zip fájlt a könyvtárban, feltételezve hogy nincs más jellegű zip fájl a backup-okon kívül.

A backupdir-t változóba tettem, mert két helyen is szerepelt, így módosításkor nincs keveredés. Valamint a "--group-directories-first" kapcsolót azért raktam be mert nem mindenhol alapbeállítás, hogy előre rakja a könyvtárakat, így a tail rész még véletlenül sem tud belebotlani egy könyvtárnévbe.

Végül az utolsó sorban a távoli szerverre történő felmásolás az scp paranccsal áttekinthetően.

Persze ha esedékes, hogy később bővül a másolni kívánt fájlok listája, akkor elegánsabban is megoldható ugyanez egy tömb használatával:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# Másoló szkript...
 
# Változók:
backupdir="/home/pisti/backup/site1/"
filelist=(
    "/var/log/ispconfig/httpd/weboldalam.hu/error.log"
    ${backupdir}$(ls -tr --group-directories-first ${backupdir}*.zip | tail -n 1)   
    "/var/www/weboldalam.hu/exports/statistics.xml"
)
 
# Másolás:
scp -P 12345 ${filelist[@]} pisti@weboldalam.hu:~/Mentesek/

Így már csak a "filelist" nevű tömb elemeihez kell hozzáadni az újabb sorokat a fájlok eléréseivel, és már másolja is őket a program.

 

Konklúzió

Legyen bármilyen egyszerű is a feladat, mindig érdemes megfontolni hogy összezsúfoljuk-e egyetlen parancssorba az egészet, mondván hogy "így is meg lehet csinálni", vagy készítünk neki egy kényelmes szkriptet, kommentekkel, változókkal, stb, amiket később könnyedén tudunk módosítani. És végül csak ezt az egy fájlt kell futtatnunk, vagy például a cron-ba betennünk.

Valamint itt láthattuk az scp parancs többféle felhasználási módját is, amivel biztonságosan tudunk másolni fájlokat a gépeink/szervereink között, amit még könnyedén automatizálni is tudunk.