Linuxová kouzla III: přenos pracovního prostředí mezi různými počítači

Poměrně velkou část přednášky Jirky Bence a Milana Vančury o linuxovém kouzlení zabraly hrátky s přenášením pracovni plochy z jednoho počítače na druhý (např. mezi domovem a zaměstnáním) a k jakým zajímavým záležitostem to využít. Dnes se to naučíte také!

V dnešním díle seriálu linuxových kouzel podle stejnojmenné přednášky předváděné na LinuxExpo2007 si ukážeme, jak na jiném počítači pokračovat v práci na své původní pracovní ploše, ať je ten jiný počítač kdekoliv. Aplikace zatím mohou běžet a vůbec netuší, že já běžím také, např. ze zaměstnání domů. Dokonce na tom druhém počítači ani nebudu potřebovat mít uživatelské konto.

Že jsou to kouzla? No a od toho tu přece jsme, že?

Tak vzhůru do toho. Základem všeho je technologie NX popsaná na stránkách [?:http://www.nomachine.com/ www.nomachine.com]. O co se jedná? Již od začátku umožňuje protokol systému X window práci přes počítačovou síť. Kdo jste si ale zkoušel takto pracovat přes některou z pomalejších možností připojení k Internetu (modem, GPRS atd.), asi jste zjistili, že praktická použitelnost je velmi nouzová. V praxi se tak toto použití hodilo hlavně na sítích LAN. Protokol X je hodně náročný na přenosové pásmo, a tak byla snaha vymyslet proxy s keší, která by tuto komunikaci urychlila. Že se nejedná o žádnou jednoduchou záležitost, svědčí stránka s popisem použitých algoritmů a technik:

[?:http://web01.nomachine.com/documentation/NX-XProtocolCompression.php web01.nomachine.com/documentation/NX-XProtocolCompression.php]

Pokud tedy nainstalujeme na server balíček nxserver a na klienta nxclient, pak po přihlášení pomocí NX (místo přímého přihlášení do X) můžeme nejen rychleji a pohodlněji pracovat, ale můžeme i klientskou část pozastavit, později spustit z jiného počítače a tam v práci pokračovat. Aplikace v naší X relaci na serveru si stále myslí, že mají svůj X server k dispozici, protože serverová část NX proxy stále běží a zajišťuje potřebné služby. Proto si takto můžeme přenášet pracovní plochu mezi počítači i uprostřed práce.

My si takovou instalaci ukážeme a celý efekt vylepšíme o to, že na klientském počítači není třeba mít vlastní účet, dokonce se není nutné ani přihlašovat. Postačí nám jen (prázdná) USB klíčenka.

Po vložení USB klíčenky do libovolného počítače se otevře naše pracovní plocha právě tak, jak jsme ji naposledy zanechali. Po vyjmutí klíčenky (bez odhlášení) pracovní relace opět zmizí, klíčenku můžeme vložit do jiného počítače a pokračovat v práci tam.

Popis řešení

Na serveru je databáze sériových čísel USB klíčenek a k nim odpovídajících konfigurací a identifikátorů příslušných NX relací (session). Po vložení klíčenky do USB portu na klientovi se spustí skript, který se pomocí ssh připojí na server, zjistí údaje pro NX a následně spustí NX klienta s parametry náležejícími USB klíčence tohoto sériového čísla. Relace tedy obsahuje pracovní plochu uživatele na serveru - z libovolného klienta, ať je na klientovi přihlášen pod libovolným jiným uživatelským jménem. Nebo dokonce není přihlášen vůbec. Postačující údaj je sériové číslo USB klíčenky. (Pokud by vám to nevyhovovalo, je možnost chránit relaci heslem.)

Jelikož chceme, aby efekt fungoval jak v již existující pracovní ploše přihlášeného uživatele, tak i na přihlašovací obrazovce (kdm), musí klientský skript řešit, zda je spuštěn v době přihlašování nebo uvnitř běžící relace, a zajistit synchronizaci a restart potřebných služeb.

Vlastní myšlenka je velmi jednoduchá a můžete si vyzkoušet i vlastní řešení nebo upravovat toto podle vlastních potřeb. Ať už z důvodu vyššího pohodlí nebo např. kvůli tomu, že na vaší speciální konfiguraci klienta toto řešení bez úprav nefunguje zcela. Uvedené řešení se nesnaží pokrýt nejobecnější případy; je to jen ukázka toho, jak daný problém řešit.

0. Přípravy

Ze stránek [?:http://www.nomachine.com/ www.nomachine.com] stáhneme balíčky: NX Free Edition for Linux, NX Node for Linux a NX Client for Linux. Na systém se kvůli závislostem musí nainstalovat v pořadí nxclient, nxnode a nxserver. To samozřejmě platí pro server. Na klientské počítače postačuje nainstalovat balíček nxclient.

Nyní si můžete vyzkoušet vlastní připojování, bez vazby na klíčenku. Např. si zkuste připojit se NX relací k serveru (příkaz nxclient) a poté na serveru napsat příkaz:

nxserver --list

Pak na klientu kliknout na zavírací křížek okna s NX relací, zvolit akci "Suspend" a opět se podívat na serveru na výpis relací. Všimněte si nejen změny stavu relace, ale i toho, že "suspendovaná" relace nemá k sobě navázanou žádnou IP adresu klienta, protože nyní se můžeme k této relaci připojit odkudkoliv na světě. Ještě před pozastavením relace si můžete vyzkoušet některé triky jako přenášení obsahu schránky mezi vzdálenou a lokální pracovní plochou.

Na straně klienta vidíme, že u uživatele, ktery se připojil NX klientem, vznikl adresář ~/.nx/ a v něm podadresář config obsahující konfigurační soubory s údaji odpovídajícími těm naklikaným v grafickém rozhraní NX klienta. Tyto konfigurační soubory budou později uložené v databázi na serveru a k nim informace, k jaké USB klíčence patří.

Po seznámení s NX přistoupíme k práci na vlastním efektu s klíčenkou.

1. Reakce na událost vložení a vyjmutí klíčenky

Tuto část obstarává subsystém udev; ten zavolá hlavní skript nxc.sh. Do pravidel pro udev vložíme tento soubor:

/etc/udev/rules.d/61-local.rules:

ACTION=="add", KERNEL=="sd[a-z]", ENV{ID_BUS}=="usb", RUN+="/usr/local/sbin/nxc.sh on $env{ID_SERIAL} $devpath"
ACTION=="remove", KERNEL=="sd[a-z]", RUN+="/usr/local/sbin/nxc.sh off $devpath"

2. hlavní skript nxc.sh

Spojí se se serverem a provede akci podle události:

Při vložení klíčenky zjistí na serveru konfigurační údaje NX pro relaci svázanou s touto klíčenkou a spustí nxclient s těmito parametry. Při startu nxclienta zjišťuje, jestli momentálně na klientu běží kdm (pak spustí nxclient jako program přes celou obrazovku místo kdm) nebo jestli je někdo přihlášený. V takovém případě spustí nxclient v okně lokální relace právě přihlášeného uživatele.

Při vyjmutí klíčenky relaci pozastaví (suspend) a příp. restartuje kdm. Jelikož v momentě odpojení klíčenky už neznáme její seriové číslo (už je odpojená), musíme si předem uložit informaci o vazbě USB_identifikátor---seriové_číslo.

Pozn.: ve skriptu se musí řešit některé podúkoly, které ho ve výsledku znepřehledňují. Např. poměrně obtížný problém je tak zdánlivě snadná věc jako zjistit jméno uživatele, který je právě přihlášen na lokálním X serveru (:0.0).

/usr/local/sbin/nxc.sh:

#!/bin/bash

echo "nxc: $@;;;" >>/var/log/nxc.log
# NXC
# ---
# get the NX session config file according the key got as $2; run NX session

# Author: Milan Vancura Thu Apr 12 12:32:27 CEST 2007

# constants

NXSERVER=ghost
KEYFILE=/root/.ssh/nxcmd_dsa
CONFDIR=/var/run/nxclientdb

#

=======================================================================

set -e
exec 2>>/var/log/nxc.log

usage()
{
echo -e "nxc usage:\nnxc on \nnxc off \n\nnxc must be run as root" >&2
exit 1
}

die()
{
echo $2 >&2
exit $1
}

# params check

# [ ( "$1" != "on" -a "$1" != "off" ) -o -z "$2" ] && usage

event="$1"

case "$event" in
"on")
key=${2//_/}
[ -z "$3" ] && usage
usbid=$(echo "$3" | md5sum)
usbid=${usbid/ */}
# get the owner of display :0.0
dname=$(ps auxwww | grep '[/ ]X\(org\|free\|11\)* \(.* \)*:0 ' | ( read a1 a2 a3 a4 a5 a6 atty arest ; ls -l /dev/$atty 2>/dev/null | ( read a1 a2 aowner arest ; echo $aowner ) ))
# get the configuration according to the $key
rm -f ${CONFDIR}/$usbid.sess ${CONFDIR}/$key.nxs
echo "on $key" | ssh -i ${KEYFILE} root@${NXSERVER} >${CONFDIR}/$key.nxs
if [ -z "$dname" -o "$dname" = "root" ]; then
dname=$(grep -m 1 User ${CONFDIR}/$key.nxs | sed 's/^.*value="\([^"]*\)".*$/\1/')
killkdm=1
else
killkdm=0
fi
dgroup=$(id -gn "$dname" 2>/dev/null)
chown "$dname:$dgroup" ${CONFDIR}/$key.nxs
ln -s $key.nxs ${CONFDIR}/$usbid.sess
# finally run nxclient for the user and session we got
if [ $killkdm -eq 1 ]; then
rckdm stop
while ps auxwww | grep -q '[/ ]X\(org\|free\|11\)* \(.* \)*:0 ' ; do
sleep 1
done
su - "$dname" -c "xinit /usr/local/bin/X_nx_client --session ${CONFDIR}/$key.nxs -- /usr/bin/X :0" &
else
su - "$dname" -c "DISPLAY=:0.0 nxclient --session ${CONFDIR}/$key.nxs" &
fi
;;
"off")
usbid=$(echo "$2" | md5sum)
usbid=${usbid/ */}
[ -L ${CONFDIR}/$usbid.sess ] || die 2 "Session $usbid doesn't exist"
key=$(find ${CONFDIR}/$usbid.sess -printf "%l\n")
key=${key/.*/}
echo "key=$key;;" >&2
echo "off $key" | ssh -i ${KEYFILE} root@${NXSERVER} || true
if killall X_nx_client ; then
sleep 1
while ps auxwww | grep -q '[/ ]X\(org\|free\|11\)* \(.* \)*:0 ' ; do
sleep 1
done
fi
rckdm start
;;
*)
usage
esac

3. pomocné skripty a soubory na straně klienta

/usr/local/bin/X_nx_client: (řeší problém odpojení programu nxclient a tudíž ukončení xinit okamžitě po jeho startu)

#!/bin/bash
$(which nxclient) "$@"
while true; do
sleep 1000
done

/usr/local/bin/X_nx_server - pro speciální nastavení X serveru, možno nahradit přímým voláním X

/root/.ssh/nxcmd_dsa a /root/.ssh/nxcmd_dsa.pub: pár ssh klíčů určených pro komunikaci se serverem; s prázdnou passphrase

/var/run/nxclientdb: adresář pro uložení informace o vazbě USB_id - seriové číslo klíčenky na klientské straně.

4. serverová část

Jelikož požadujeme, aby technická komunikace se serverem probíhala bez nutnosti vložení dalšího hesla (a uživatel běžně ani heslo uživatele root nemůže znát), využijeme možností ssh a k serveru se skript nxc.sh připojuje pomocí speciálně vytvořeného klíče. Na straně serveru pak potřebujeme tento klíč navázat na skript provádějící serverovou část akce, abychom nevyrobili přístup na účet uživatele root bez hesla.

Proto do /root/.ssh/authorized_keys přidáme veřejnou část klíče nxcmd_dsa a doplníme ji o spouštěný (vnucený) příkaz. Řádek pak bude vypadat přibližně takto:

command="/root/nxdb.sh" ssh-dss AAAAB3NzaC1kc3MAA....

/root/nxdb.sh:

#!/bin/bash

CONFDIR=/root/nxdb

read action key rest

case $action in
on)
[ -r $CONFDIR/$key.nxs ] || exit 1
cat $CONFDIR/$key.nxs
;;
off)
[ -r $CONFDIR/$key.sess ] || exit 1
nxserver --suspend $( ;;
esac

Vidíme, že skript na serverové straně je velmi jednoduchý: očekává na standardním vstupu jeden řádek se dvěma slovy: první je název akce (on/off) a druhé je identifikátor relace (tj. seriové číslo navázané USB klíčenky). Při akci "on" pak vrátí konfigurační soubor příslušné relace a při akci "off" relaci odpovídající identifikátoru zastaví.

5. První spuštění

Před prvním použitím každé NX session je potřeba zavést informaci o ní do databáze na serveru.

Nejdříve vybereme USB klíčenku, která bude s touto relací spojená, a běžným způsobem ji připojíme do systému. Potom v adresáři /dev/disk/by-id/ vidíme soubor s názvem tvořeným jejím seriovým číslem. To si opíšeme a po vymazání podtržítek z něj získáme vnitřní identifikátor relace. Není třeba se obávat, s tímto dlouhým identifikátorem se pak při používání už nikdy nesetkáme :-) Jen je důležité dát pozor, abychom neopsali identifikátor diskového oddílu místo identifikátoru celého disku (na konci nesmí být žádné ...-part1 a podobně). USB klíčenku odpojíme a vytáhneme z USB portu.

Nyní se přihlásíme na server jako uživatel, k jehož relaci se chceme hlásit. (Na přednášce to byl uživatel jožin.) Spustíme příkaz:

nxclient --wizard

a tím vytvoříme novou session. Jako její jméno zadáme výše získané seriové číslo USB klíčenky zbavené podtržítek. Zadáme jméno serveru, kam se budeme připojovat (samozřejmě musíme zadat internetové jméno, ne "localhost", i když jsme momentálně na stejném počítači). Na konci průvodce zvolíme možnost "open Advanced dialog". Tam zvolíme další parametry podle našich potřeb (např. velikost okna, spouštěné prostředí atd.). Pokud chceme, aby se nás později neptal klient na heslo, zaškrtneme též "Remember password". Uložíme (Save) a opustíme dialog (OK). Zadáme jméno a heslo uživatele a po odkliknutí tlačítka Login by se měla otevřít požadovaná relace. Po stisku zavíracího křížku okna s relací se objeví nabídka Suspend/Terminate/Cancel. Zvolíme Suspend a tím se relace uloží, neukončí (programy v ní spuštěné běží dál!) a jen klient se od ní odpojí.

Nyní máme obě části informace: uloženou session i seriové číslo klíčenky. Vložíme tyto informace do databáze na serveru. Přihlásíme se jako uživatel root a provedeme (předpokládáme dále jméno uživatele session jožin - jako na
přednášce):

mkdir ~/nxdb
cd ~/nxdb/
cp ~jozin/.nx/config/$SERIOVECISLO.nxs .
nxserver --list jozin
echo $SESSIONID >$SERIOVECISLO.sess

Parametry $SERIOVECISLO a $SESSIONID nahradíte hodnotami z vašeho systému. $SERIOVECISLO už známe a $SESSIONID získáte příkazem "nxserver --list jozin", sloupec "Session ID".

To je vše. Nyní na libovolném počítači - klientovi, kde je nainstalovaná klientská část řešení, můžete zkusit zasunout tuto klíčenku a objeví se okno (v případě už běžícího jiného přihlášení) nebo celá nová obrazovka (v případě kdm) s pracovní plochou jožina na serveru. Po vytažení klíčenky tato pracovní plocha opět zmizí a pokud nikdo nebyl přihlášen na klientovi, tak se obnoví kdm.

Autor: koty