Named pipe

Predstavme si nasledujucu situaciu:

Potrebujeme si stiahnut subor o velkosti 100 GB zo vzdialeneho ftp servera. Tato uloha nam bola znacne skomplikovana, pretoze:

Nas pristup do siete je obmedzeny proxy serverom. Proxy server nam neumoznuje nic ine, nez pripojit sa na porty 80 a 443 vzdialenych systemov (bezna prax v mnozstve firiem). Mame sice k dispozicii shell konto na nejakom serveri, ktory umoznuje ssh spojenia na porte 443, tam vsak mame quotu vo velkosti 1 GB (dalsim neprijemnym obmedzenim moze byt aj obmedzenie velkosti suboru na napr. 35 MB). Ako tento problem vyriesime?

V prvom rade si musime zariadit moznost pripojenia sa na ssh server cez proxy. Pomoze nam v tom balik corkscrew

$ yum install corkscrew

Vytvorime si autentikacny subor pre corkscrew, ktory bude v nasom homedire a bude obsahovat nase uzivatelske meno a heslo pre autentifikaciu na proxy serveri:

# echo "username:password" > ~/.corkscrew-auth

Potom si upravime nas pouzivatelsky ssh configurak tak, aby sa pripojil na server pomocou corkscrew cez proxy server s autentifikaciou a to tak, ze do suboru ~/.ssh/config pridame tieto riadky:

host hostname_ssh_servera,_na_ktorom_mame_shell_konto

ProxyCommand corkscrew hostname_proxy_servera port_proxy servera %h %p /home/nase_lokalne_username/.corkscrew-auth

Potom spojenie otestujeme:

ssh -p 443 hostname_shell_konto

Voila, sme pripojeni k ssh serveru a mozeme pouzivat nase shell konto cez firemny proxy server bez toho, aby ktokolvek vedel, ze to robime.

Prve, co na vzdialenom ssh serveri urobime, je named pipe:

# mkfifo pipe

Teraz mame na servery pipu, ktora je schopna prijimat data na vstupe a poskytnut ich na vystupe.

Na lokalnom stroji potom urobime

# ssh -p 443 nase_username_na_shell_servery@shell_server_hostname 'cat pipe' > sto_gigovy_subor.ndr.cz.tar.gz

Tymto sa pripojime na shell server, nechame si programom cat vypisat data z vystupu nasej vzdialenej rury na nas lokalny vystup, ktory hned presmerujeme do suboru. Po zadani tohoto prikazu sa zatial nic nedeje, lebo do vzdialenej rury zatial netecu ziadne data, ale prikaz cat caka na EOF, ktory vsak zatial nedostal a tak pekne caka dalej. My sa medzitym znova prihlasime na shell server a tam urobime dalsi dolezity krok:

wget -O - url_sto_gigoveho_suboru|dd of=pipe

Tymto zavolame program wget, ktory sa pripoji na vzdialeny ftp server a zacne stahovat dany subor. Parameter -O prinuti program wget ukladat stiahnute data do suboru, ktory mame nastaveny na - a to je standardny vystup. Ten mame presmerovany do programu dd, ktory ho na zaklade parametra of=pipe posiela do nasej rury. (to dd je tam v podstate uplne zbytocne, ani neviem, preco som ho pouzil :>) Teraz uz rura poskytuje realny vystup, ktory je na nasom lokalnom pocitaci zapisovany do suboru. Filesize limit nasho shell konta nie je uplatnovany, pretoze pipa ma v idealnom pripade nulovu velkost. Quota sa tiez neuplatnuje, pretoze ziadne zo stahovanych dat sa neukladaju na disku vzdialeneho shell servera, ale prudia hned prec - k nam.

Named pipe ma jednu vynikajucu vlastnost - ak sa jej buffer zaplni, zablokuje svoj vstup. Pri nasej implementacii sa to sprava tak, ze wget sa stopne, ale proces stale bezi. To v praxi znamena, ze citanie vystupu pipy mozeme docasne zastavit a potom znovu spustit bez toho, aby sme prisli o data. Takto nam teda nevadi, ze sirka pasma medzi nasim lokalnym pocitacom a shell serverom je mensia, ako sirka pasma medzi shell serverom a vzdialenym ftp serverom. wget bude data stahovat prave takou rychlostou, akou mu to pipa dovoli. Toto si mozeme otestovat tak, ze pri zapisovani dat z pipy na lokalny pocitac stlacime ctrl+z. Proces sa pauzne a na shell serveri vidime, ze sa zastavil aj wget. Potom, co na lokalnom pocitaci zadame fg vidime, ze wget sa zase pekne rozbehne.