Jít na obsah Jít na navigaci Jít na vyhledávání

Aktualizace Steam klienta rozbila mnoho her

Srpnová aktualizace Steamu přinesla problémy nemálo uživatelům Linuxu, kteří používají Wine. Když jsem se chtěl včera na chvíli odreagovat u hry, hodinu jsem řešil problém jen proto, abych si mohl necelou další zahrát. O co jde?

Konkrétní kombinace mnoha systémových faktorů způsobila okamžité pády po načtení hry. Potýkal jsem se s problémem u Source enginu, konkrétně u titulů Counter-Strike: Source a Half-Life 2: Deathmatch. Hra se načetla, zobrazila se MOTD, ale po kliku na OK skončila veškerá zábava.

Do problému jsou zahrnuty následující faktory:

  • aktualizovaný Steam Client,
  • Wine 1.3.0 a vyšší,
  • GCC 4.5 a nižší,
  • nastavení flagů GCC -march=native nebo -mtune=native,
  • Core 2 Duo procesor.

Podle dosavadních informací tato aktualizace Steamu vynutila použití části Steam Community In-Game, konkrétně knihovny GameOverlayRenderer.dll, která je za problémy odpovědná. Řešení problému jsou dvě. Buď překompilovat Wine s použitím jiných flagů kompilátoru (neověřeno, uživatelé však hlásí úspěch), nebo úplně zakázat použití knihovny GameOverlayRenderer.dll. Nutno podotknout, že v GCC 4.5 již In-Game funguje.

Možnost druhá je podstatně jednodušší, stačí spustit winecfg, v záložce Knihovny/Libra­ries zadat gameoverlayrenderer a nastavit na Zakázat/Disable.

Odkazy

Štítky:

Pohodlná synchronizace s Gentoo Portage

Většina uživatelů Gentoo jsou silní geekové a tuto distribuci si vybrali právě kvůli jejímu balíčkovacímu systému – Portage. Ten funguje na systému tzv. rolling updates a pro uživatele je tudíž výhodné pravidelně svůj systém aktualizovat. Ze začátku jsem si vystačil s manuálním psaním příkazů, ale postupem času mě to přestalo bavit, a proto jsem si napsal komplexnější skript.

Skript je pevně svázaný s balíčkovacím softwarem Paludis, klientem cave (více o něm v předchozím článku). Je interaktivní v jediném případě, kdy zobrazuje potvrzení o prováděných akcích, supluje tak vlastnost emerge -a. K tomuto účelu použije buď emulátor terminálu Konsole a KDialog z prostředí KDE 4, nebo v případě nedostupnosti KDE či grafického prostředí přejde na roota a pro dialog použije read.

Požadavky skriptu stručně:

  • bash, sudo
  • cave, eix
  • KDE 4, Konsole, KDialog

Zkušení uživatelé jistě nebudou mít problémy takto jednoduchý kód v případě nutnosti upravit.

#!/bin/bash

case "$1" in
        root)
                # sync repositories
                cave sync
                # update eix database
                eix-sync -u
                # show user what we like to update
                cave resolve -c world
                # ask user if he really want to do that
                kdialog=$( which kdialog )
                text="Continue in merging new packages?"
                if [ "$DISPLAY" != "" -a ! -z "$2" ]; then
                        su "$2" -c "$kdialog --yesno \"$text\""
                else
                        read -p "$text (y/n) "
                fi
                if [ "$REPLY" == "n" -o $? -ne 0 ]; then
                        exit 1
                else
                        cave resolve -cx world
                fi
                # search for broken packages
                if [ $? -eq 0 ]; then
                        cave fix-linkage -x
                fi
                ;;
        *)
                # open root console, determine if Konsole is opened
                script="$( realpath "$0" ) root"
                if [ "$KDE_SESSION_UID" == "$( id -u )" ]; then
                        sudo echo -n
                        # open session called "Root" with working directory "/root"
                        ROOT_SESSION=$( dbus-send --session --dest=org.kde.konsole --type=method_call --print-reply=number /Konsole org.kde.konsole.Konsole.newSession string:"Root" string:"/root" | cut -c 10- )

                        sleep 0.2
                        qdbus org.kde.konsole /Sessions/${ROOT_SESSION} org.kde.konsole.Session.sendText "$( echo "$script $USER" $'\r')"
                else
                        sudo su - -c "$script"
                fi
                ;;
esac

Skript ke stažení: sync.sh.

Štítky:

Skript pro zálohování pomocí rdiff-backup

rdiff-backup je nástroj postavený na binárním diffu pro inkrementální zálohování dat. Sám o sobě je velmi dobrým pomocníkem, avšak v kombinaci se skriptem spouštěným pomocí cronu je ještě lepší. Tento článek nepopisuje funkcionalitu programu samotného, pouze mého skriptu.

Kdysi na mě byly pracovně kladeny požadavky pro implementaci systému zálohování dat na webhostingových serverech. Jelikož kolega aktivně využíval zmiňovaný rdiff-backup, vyzkoušel jsem ho. Jeho přístup v cronu se mi však již tak nelíbil, proto jsem vymyslel vlastní skript, jenž mi v průběhu let téměř přerostl přes hlavu. A tady je:

#!/bin/bash

# config
backupdir="/backup/"
listdir="${backupdir}filelists"
removeargs="--remove-older-than 2M --force"
mailargs="admin@dragonjake.net"

# check for arguments
if [ $# -gt 0 ]; then
        lookup="${*}*"
else
        lookup="*"
fi

# get list of servers and build arrays
cd $listdir
i=0
for server in $lookup; do
        # globbing or not
        if [[ "$server" =~ ".glob" ]]; then
                glob="$( basename $server .glob )"
                serverlist[$i]=$glob
                backupargslist[$i]="--include-globbing-filelist ${listdir}/${server}"
        else
                serverlist[$i]=$server
                backupargslist[$i]="--include-filelist ${listdir}/${server}"
        fi
        let i++
done

# function mailer(exit_code, server, out)
mailer()
{
        # if failed, send e-mail
        [ "$1" -ne "0" ] && echo "$3" | mail -s "Backup of $2 failed!" $mailargs
}

# UID protect
if [ "$( id -u rdiff-backup )" -ne "$( id -u )" ]; then
        echo "You need to be rdiff-backup to do this!"
        exit 1
fi

# backup loop
for (( i=0; i < ${#serverlist[@]}; i++ )); do
        if [ -d "${backupdir}${serverlist[$i]}" ]; then
                # remove older
                removeout=$( rdiff-backup $removeargs ${backupdir}${serverlist[$i]} 2>&1 )
                # call mailer
                mailer $? "${serverlist[$i]}" "$removeout"
        fi

        # backup now
        backupout=$( rdiff-backup ${backupargslist[$i]} ${serverlist[$i]}::/ ${backupdir}${serverlist[$i]} 2>&1 )
        # call mailer
        mailer $? "${serverlist[$i]}" "$backupout"
done

exit 0

Konfigurace a princip

Za zmínku stojí první řádky zabývající se konfigurací:

  • backupdir – adresář, kde budou zálohy umístěny,
  • listdir – adresář s filelisty (soubory obsahující seznam souborů, přesněji adresářů) pojmenovanými dle libosti,
  • removeargs – argumenty, které se použijí pro příkaz odstranění starých záloh, zde se primárně nastavuje délka uchovávání (2 měsíce v tomto příkladu),
  • mailargs – e-mailová adresa správce (na tento e-mail bude odeslán výstup programu při selhání procesu) a popř. další argumenty pro program mail (dá se změnit ve funkci mailer()).

Skript předpokládá cíle zálohování jako vzdálené stroje, rdiff-backup tudíž pracuje přes SSH. Jako parametr obdrží jméno cíle použité u filelistu, buď je tedy možné soubor s filelistem pojmenovat včetně domény (např. server1.domena­.tld) a nebo, podle mě pohodlnější možnost, definovat cíle v souboru ~/.ssh/config, např. takto:

host dragon
  hostname dragon.dragonjake.net
  user root
  identityfile /backup/.ssh/id_rsa
  cipher blowfish
  protocol 2

Na straně cílového stroje je nutné přidat SSH klíč pro uživatele, který na zálohovacím stroji spouští rdiff-backup (ve skriptu natvrdo zakódován stejnojmenný uživatel) a další nutnou konfiguraci, kterou uvádí i manuál, příklad:

command="rdiff-backup --server --restrict-read-only /",from="dragon.dragonjake.net",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsrdNbqfLUtTRgAUhzjBXTn2cruaApNbZ+KLJK1/T6nIWp9ybCaw5lOVTw7wdyx9kW0tws7xVHEKPkhZZPoBZLBQh5kvWhIgsmOIaKN58sFode/7alEs4xYEemMKSXqyhDG0yx+MguPAlxRGpb5l6oXNHZeiFwWsfAd47+w2gtyTz+aMMFRiVwtUGu+2CGkCfoSjT5nt6lYuOZFJTsvtkmel/eoFencWxpsQoJsCoXkV52dooTA4guHxATyoV/geDrQ1NLWJz3k02SR9wQ5qs1KXFl2ecFrdfxVcUlSIKe/igpZ0HTEuwzs4POpetVvlj029hJLj6kQsz72FI69c87w== rdiff-backup@dragon

Drobnou zajímavostí je možnost spustit zálohování jen pro konkrétní cíl. Stačí uvést jeho jméno jako parametr, např. /backup/backup.sh allosaurus.

Filelisty

Dostáváme se k zapeklitější funkcionalitě, kterou upřímně dle dokumentace ne zcela chápu. Jak jsem již zmínil výše, definice filelistu je nutnou podmínkou pro správnou funkčnost skriptu. Jeho obsah může být následující:

- /bin
/boot
- /cdrom
- /dev
/etc
/home
- /home/dragonjake/download
- /home/dragonjake/felnet
- /home/dragonjake/filmy
- /home/dragonjake/games
- /home/dragonjake/music
- /home/dragonjake/server
- /home/dragonjake/.wine/drive_c
- /home/dragonjake/work/livecd/root
- /lib
- /lost+found
- /media
- /mnt
- /opt
- /proc
- /root
- /sbin
- /share
- /srv
- /sys
- /tmp
- /usr
/var
- /var/tmp

Soubor říká, které adresáře počínaje / se zálohovat mají a které ne. Skript ho předá programu pomocí parametru --include-filelist. Další možností je využití globbing filelistu (--include-globbing-filelist), po kterém jsem sáhl v nouzi, když jsem rdiff-backup přes obyčejný filelist nedokázal donutit zálohovat z celého serveru pouze přesně dané adresáře. Následující ukázka globbing filelistu pojmenovaného suffixem .glob funguje:

/home/www/draci.info
/var/lib/mysql/13-draci_info
/var/lib/mysql/13-gotty
/var/lib/mysql/13-new3
/var/lib/mysql/13-new_draci
/var/lib/mysql/13-sumbion
- /

Závěrem

Skript je určen ke spouštění pomocí cronu zcela bez parametrů:

0 3     * * *   rdiff-backup    /backup/backup.sh

Upozornění: při prvním spuštění skriptu může zálohování trvat velmi dlouho. Nedoporučuji hned umisťovat zápis do cronu, nýbrž nejprve spustit ručně, např. ve screenu.

Soubory ke stažení použité ve článku:

Odkazy

Štítky:

Balíčkovací software Paludis se chce zbavit Paludise

Typicky bulvární titulek, ale v tomto případě jsem si ho nemohl odpustit, jelikož cituji přímo blog vývojáře. Kdo neví, Paludis je alternativní balíčkovací systém s podporou více formátů, momentálně ebuildů pro distribuce Gentoo a Exherbo. Vývoj se žene kupředu rychlostí blesku a již před rokem jím bylo bez větších problémů možné z velké části nahradit současný Portage. Vývojáři však nyní uvedli nový klientský program cave, který by měl jednou provždy umlčet věčné flamewary ohledně příkazové nekompatibility mezi těmito systémy.

Paludis, paludis a paludis

Paludis již od počátku disponoval klientským programem paludis, na kterém jsme všichni společně vyrostli a vžili si do paměti příkazy typu:

paludis -pi world
paludis --dl-blocks discard -i world

A nebo mé oblíbené:

paludis -pu --with-unused-dependencies --permit-unsafe-uninstalls cat/some-pkg

… a oni nám to chtějí zrušit!

Představuje se cave

Dle mého názoru naprosto nevhodně zvolené jméno programu, ale jinak cave vypadá mnohem robustněji a elegantněji. Elegance na nás srší již od prvního pohledu, kupříkladu příkaz install neexistuje, jmenuje se resolve. A když se chceme podívat do nápovědy, cave resolve --help vypíše neuvěřitelných 151 řádků! V tom aby se prase vyznalo, je tedy lepší používat man. Manuálovým stránkách dávám bod za rozčlenění, další krátkému příkazu help za jednoduchý a stručný výpis nejčastějších funkcí. Mile mě potěšil fix-linkage, díky kterému je vyřazen další klient, a to reconcilio. Pamatuji si, jak jsem prvních několik měsíců používání Paludise měl neskutečný problém vzpomenout si na ten připitomělý název, abych opravil špatné linkování knihoven. Příkaz purge zjednodušuje původní paludis -u --uninstall-unused, hlavně je hned v základní nápovědě, a tak ho člověk nemusí hledat kdesi v manuálu. Za zmínku už snad stojí jen sync, uninstall a search, jehož hledání je snad ještě zdlouhavější než dřív – a u toho se zastavím, odjakživa je nepoužitelné.

Obecná vsuvka o vyhledávání

Vyhledat jeden balíček mi trvá přibližně 5 minut, takže kešovaná SQLite databáze v programu eix je k nezaplacení. Stále se ptám, proč při operacích hledání Paludis kontroluje strukturu všech ebuildů a ještě k tomu drze vypisuje, abych přepsal řádek se SLOT="0" na SLOT=""? K čemu mi to je, běžnému uživateli? To si snad tohoto problému vývojáři nevšimli a nebo je to jen hluboký defekt ext3 filesystému v kombinaci s mým strojem, diskem či tak?

Závěrem

Před pár dny vyšla nová verze Paludise, která oficiálně publikovala i výše zmíněný cave. Zhruba hodinu jsem studoval dokumentaci a možnosti tohoto klienta a nakonec upravil svůj synchronizační skript tak, aby ho používal. Na závěr uvádím ukázky nové příkazové syntaxe včetně starších ekvivalentů:

cave sync || paludis -s --multitask
cave resolve -c world || paludis -pi world
cave resolve -cx world || paludis -i world
cave fix-linkage || reconcilio

Nutno podotknout, že při updatu world oba klienti řeší závislosti trochu odlišně. To ostatně možná zjistíte sami hned při prvním použití :)

Odkazy

Štítky:

Hezké nastavení GNU Screenu

GNU Screen je textový skoro window manager umožňující uchování otevřených terminálů uvnitř jediného okna s možností použití jako vzdálené session. Jednoduše řečeno, vezmu-li SSH spojení, screen udrží spuštěné např. irssi, centerim, SSH na další stroj a mnohem více.

Bohužel ve výchozí konfiguraci je poněkud nešťastný, protože ihned nevidíte např. otevřená okna nebo ve kterém okně momentálně jste. Navíc jsou některé klávesové zkratky nepřirozené, a proto jsem kdysi začal zkoumat manuál a možnosti konfigurace. Naneštěstí jsem dlouho nebyl úspěšný. Nakonec mi však kamarád Jedjisch poslal svůj konfigurační soubor, který téměř vyřešil veškeré mé problémy.

Celý konfigurační soubor se do článku nevejde, proto prosím použijte odkaz pro stažení na konci článku. Za zmínku stojí přemapované klávesy pro aktivaci okna 0 a 10, ke kterým se na české klávesnici přistupovalo špatně, upravený řádek hardstatus, který na spodním řádku screenu ukazuje barevně výpis oken (barevné kódy dalo práci zjistit, nakonec vyhrála metoda pokus-omyl), nastavení monitorování aktivity a výchozího okna v posledních řádcích souboru.

Konfigurační soubor je k dispozici zde. Přejmenujte na .screenrc a umístěte do domovského adresáře. Pro načtení do již běžícího screenu použijte příkaz:

^a :source ~/.screenrc

kde ^ značí klávesu Control.

Štítky:

E-mailové logování v syslog-ng

K tomuto nápadu mě kdysi přivedl kamarád Chytrex během jednoho z mnoha povídání o své náplni práce. Ve stručnosti, přijde tiket (v konkrétním příkladu mi byl ukázán řádek ze systémového logu), a jeho úkolem je problém vyřešit. A to mi vnuklo nápad nechat si zasílat problémy ze syslogu na e-mail.

Chvíli jsem googlil a nakonec našel jednoduchý perl skript (zdroj již bohužel neznámý), který se nechá pouštět od syslog-ng a hloupě přeposílá zprávu přes sendmail. Několik let mi to takto stačilo, ale pak mě začaly obtěžovat zprávy s nesmyslně vysokou facility (prioritou) bez jakékoli informační hodnoty. Rekompilovávat upravené zdrojové kódy několika balíčků mě po chvilce přestalo bavit, a tak jsem skript obohatil o pár řádků s podporou klíčových slov k vyloučení (viz pole @exclude).

#!/usr/bin/perl -n
# thanks to Brian Dowling for an example with security in mind.

$TO = 'admin@dragonjake.net';
$FROM = 'system@dragon.dragonjake.net';
@exclude = ("_nss_mysql_getspnam_r conf file parsing failed", # nss-mysql
            "Statement may not be safe to log in statement format", # mysql-server
            "Error getting poly dir context, No data available", # pam
            "sshd.+(already in use|cannot listen to port)", # sshd
            "pam_namespace.+Unmount" # pam
           );

foreach $item (@exclude) {
        if ($_ =~ m/$item/i == 1) {
                exit;
        }
}

s/^<\d{1,2}>//;

open(MAIL, "|/usr/sbin/sendmail -t -i");

print MAIL << "EOT";
To: $TO
From: $FROM
Subject: Log Alert: $_

$_

EOT

close(MAIL);

Skript by sám o sobě nefungoval, a tak je potřeba syslog-ng sdělit, že ho chceme používat. Vlastní filtry f_grsec a f_nmail používám pro omezení zbytečného spamu generovaného grsec patchem a mailserverem. Představte si totiž případ, kdy se mailserver rozbije a syslog-ng začne jeho chybové hlášky ukládat jako e-maily k odeslání. Výsledkem je téměř nekonečná smyčka chyb a fronta přesahující velikost několika tisíců e-mailů. Konfigurace v útržcích vypadá následovně:

...
# e-mail alert
destination da_admin { program("/home/bin/syslog-alert.pl"); };
...
# ignore grsec spam
filter f_grsec { not match("grsec"); };
filter f_nmail { not facility(mail); };
...
# e-mail alert with at least err priority
log {
        source(s_all);
        filter(f_grsec);
        filter(f_nmail);
        filter(f_at_least_err);
        destination(da_admin);
};

Filtr f_at_least_err je v mé distribuci (Debian, Ubuntu) nativně, pro jistotu uvedu jeho definice:

filter f_at_least_err { level(err..emerg); };

Štítky:

Zrádné Ctrl+S a Ctrl+Q při práci v terminálu

Stává se vám, že se při práci emulátor terminálu zasekne? Nereaguje, bušení do klávesnice nepomáhá a jediná možnost je tvrdý kill? Možná jste omylem narazili na kouzelnou klávesovou zkratku Ctrl+S

Proč?

Zkratka Ctrl+S (dále jen ^S) a její opačný ekvivalent Ctrl+Q (dále jen ^Q) řídí funkce takzvaného flow control, v překladu řízení toku. V dobách minulých a již dávno zapomenutých totiž neexistovaly emulátory terminálů. Hádáte správně, byly pouze terminály. Takový terminál je obecně vzato kus hardware s monitorem, klávesnicí a komunikačním portem (foto). Terminál se pak připojí k cílovému počítači a práce může začít. Avšak aby komunikace mohla probíhat správně, je potřeba definovat protokol. A zde přichází kámen úrazu. Řízení toku musí být implementováno oběma komunikujícími stranami, což je splněno i v dnešní době na nám moc dobře známých softwarových emulátorech.

Jak se toho zbavit?

Obecně vzato, příkaz ^S potlačuje výstup a příkaz ^Q toto potlačení ruší. Někteří by mohli namítat, ale je důležité si uvědomit, že výstup v chápání terminálu znamená i vytištění napsaného textu. Proto se ^S chová, jako by způsobil úplné zamrznutí.

Naštěstí je řešení jednodušší, než by se mohlo zdát. Černou magii odstraní příkaz:

stty -ixon -ixoff

Tento řádek doporučuji umístit do .bashrc či do jiného souboru vykonávaného při inicializaci vašeho oblíbeného shellu.

Odkazy

Štítky:

Šetříme interní paměť v T-Mobile G1 - Android

Po updatu na CyanogenMod 4.2.7 se mi v trayi telefonu opět objevila nepříjemná ikonka signalizující nedostatek místa v interní paměti telefonu. Na tom by nebylo zas až tak nic špatného, kdyby mi z nenadání přestala fungovat synchronizace a download aplikací v Marketu. Obětoval jsem celé odpoledne na to, abych zjistil, že onu nefunkční synchronizaci má za následek právě nedostatek místa, na který jsem byl non-stop upozorňován. Takže co s tím?

Apps2sd

Řešení integrované přímo do CyanogenModu spočívající v jednoduchém shell skriptu, který pří bootu telefonu na základě předpokládané existence druhého diskového oddílu na SD kartě tento oddíl použije a přesune na něj veškeré nainstalované aplikace a data s nimi související. Nevýhodou je předchozí úprava karty pomocí nástrojů na dělení disku a naformátování na linuxový filesystém ext2/3/4. Za odměnu ale dostanete přenositelné aplikace i s nastavením. Skript pracuje zcela automaticky, tudíž stačí jen mít připravenou partition.

Mé vlastní řešení

Přišel jsem na něj doslova metodou pokus-omyl. Při šťourání se v datové partition jsem si všiml adresáře /data/dalvik-cache, který zabíral úctyhodných 40 MB a tím pádem byl ihned nominován za největšího žrouta místa. Tento adresář slouží běhovému prostředí Dalvik VM jako cache optimalizovaného bytekódu, jinými slovy jako úložiště překompilovaných a upravených binárek používaných aplikací. Do detailu Dalvik buduje strom závislostí jednotlivých tříd (funkčních celků aplikace) tak, aby nainstalovaná aplikace běžela co možná nejlépe. Tento strom je regenerován při každé aktualizaci ROM, proto první boot po updatu trvá i několik minut.

Dalším zajímavým místem je adresář /cache, který je stále téměř prázdný. V dosavadním Androidu je použit výhradně jako dočasné úložiště pro stahované aplikace v Marketu, jenže v poměru velikosti celé parititon (~60 MB) a jednoho stahovaného balíčku (řádově jednotky MB) je až škoda toto místo nevyužít. Proto jsem si napsal krátký skript, který dalvik-cache přesune do tohoto volného prostoru.

#!/system/bin/sh

# move dalvik cache from internal data memory to /cache
if [ ! -d /cache/dalvik-cache ];
then
    mkdir /cache/dalvik-cache
fi

busybox chown 1000:1000 /cache/dalvik-cache
busybox chmod 771 /cache/dalvik-cache

if [ -d /data/dalvik-cache ] && [ ! -h /data/dalvik-cache ];
then
    busybox cp -a /data/dalvik-cache/* /cache/dalvik-cache
    busybox rm -f /data/dalvik-cache/*

# bind mount dalvik-cache
busybox mount -o bind /cache/dalvik-cache /data/dalvik-cache

Tento skript stačí umístit např. jako /etc/init.d/06custom. Toho můžeme efektivně docílit vytvořením souboru na SD kartě a následným zkopírováním do systému těmito příkazy:

mount -o remount,rw /system
cp /sdcard/06custom /etc/init.d
chmod 755 /etc/init.d/06custom

… a pokračovat rebootem telefonu.

Pokud jste vše udělali správně, máte nyní v interní paměti (aka /data) okolo 40 MB volného místa. Povedlo se!

Pozn.: Uvedený postup je třeba opakovat po každém updatu ROM, kdy dojde k přepsání systémové partition a tedy i vlastního skriptu. Doporučuji proto skript na SD kartě ponechat a před bootem do updatlé ROM spustit konzoli a zopakovat příkazy uvedené výše.

Štítky:

Polyinstancování adresáře /tmp

Trocha teorie

Dlouholetým problémem UNIXově založených operačních systémů je adresář /tmp sloužící jako dočasné úložiště pro všechny. Tento adresář má práva nastavená na rwxrwxrwx, tedy zápis pro kohokoli. Nevýhodou však byl i absolutní přístup k datům jiných uživatelů, a proto byl zaveden tzv. sticky bit, který omezuje zápis pouze na soubory a adresáře vlastněné patřičným uživatelem. Každý tedy může zapisovat nové soubory, ale jen do těch existujících, které vlastní.

Novou možnost fyzické separace pak nabízí tzv. polyinstantia­tion. Každému uživateli namapuje daný adresář na jiný, pro něj v původní cestě nepřístupný. V případě adresáře /tmp by se např. jednalo o mapu z /tmp-inst nebo klidně i /tmp/users. Mechanismus, který polyinstancování zajišťuje, automaticky vytvoří adresář dle uživatelského jména a jím nahradí cílový adresář dle mapy.

Ukázka z praxe

Nastavení se provádí v konfiguračním souboru /etc/security/namespace.conf prostřednictvím PAM modulu pam_namespace.so:

# /etc/security/namespace.conf
#
# See /usr/share/doc/pam-*/txts/README.pam_namespace for more information.
#
#/tmp     /tmp-inst/            both      root,adm
#/var/tmp /var/tmp/tmp-inst/    both      root,adm
#$HOME    $HOME/$USER.inst/inst- context
/tmp      /tmp/users/           user      root

Zakomentované příklady zahrnují polyinstancing /tmp, /var/tmp (který osobně doporučuji nastavit jako symbolický odkaz do /tmp) a domovského adresáře uživatele. Důležitý parametr je typ, který zpravidla může být:

  • user (na základě uživatelského jména)
  • context (na základě bezpečnostního kontextu, pouze SElinux)
  • both (obojí)

Poslední čtvrtý parametr udává výjimky. V mém případě bude na základě uživatelského jména namapován adresář /tmp z /tmp/users s výjimkou uživatele root.

Jak na to

Nejprve vytvoříme adresář, ze kterého budeme mapovat, v mém případě /tmp/users. Tomuto adresáři nastavíme z bezpečnostních důvodů nulová práva a zadáme mapu v konfiguračním souboru /etc/security/namespace.conf.

Nyní je třeba pečlivě zvážit nastavení modulů PAM. Po zkušenostech z praxe nedoporučuji spouštět PAM modul ve všech případech autentizace (soubor /etc/pam.d/common-session, způsobí to více problémů než užitku. Polyinstancování jsem proto zúžil na dva jediné typy autentizace – login a sshd.

Ukázka začlenění PAM modulu do souboru s autentizací:

# Enable polyinstantiation
session    required   pam_namespace.so

Je třeba dát si pozor na to, kam modul umístíme. Existují místa, kdy je moc brzy a kdy zase moc pozdě – lepší je si to párkrát zkusit a pozorně sledovat logy (např. auth.log). Pokud se mechanismus aplikuje, měli bychom po novém přihlášení mít adresář /tmp v ideálním případě prázdný. Přihlásíme-li se na roota, měli bychom vidět /tmp/users a v něm adresář s naším a případně dalšími uživatelskými jmény. Máme hotovo.

Osobně mám přímé přihlášení na root uživatele zakázané a přistupuji přes sudo. Bohužel v tomto případě se mi nepodařilo sudo nijak donutit vyvolat čistý login (nejspíše proto, že sudo je spouštěno z shellu, na který již bylo polyinstacování aplikované), takže ani po přihlášení na roota mi /tmp neodhalil žádná svá tajemství. Pokud nedejbože nutně potřebuji vidět obsah neořezaného /tmp, obejdu bezpečnostní mechanismus mountnutím root partition např. do /mnt a podívám se tam :)

Štítky:

Awstats rychle a jednoduše

Awstats je skript v Perlu, který zpracovává logy (nejen) webserveru a ve výsledku vyplivne pěknou statistiku přístupů. Dnes si ukážeme, jak Awstats lehce a efektivně nastavit.

Awstats

Standardní konfigurace Awstats se nachází v adresáři /etc/awstats, kde je i ukázkový soubor awstats.conf. Jelikož konfigurace podporuje funkci Include, využijeme tento soubor jako základ pro naše vlastní konfigurace.

Vytvoříme nový soubor awstats.domain.tld.conf:

# hlavní config, nejprve jej vhodně nastavíme (formát logů, pluginy atd.)
Include "/etc/awstats/awstats.conf"
# log soubor Apache (v mém případě)
LogFile="/home/www/logs/domain.tld.log"
# doména, povinný parametr, který se spíše uplatní při použití spojeného logu (o tom později)
SiteDomain="domain.tld"
# aliasy pro SiteDomain, doporučuji tento formát
HostAliases="REGEX[domain\.tld$]"

Apache 2

Nastavíme Apache, aby logoval. Direktiva CustomLog se může nacházet uvnitř i vně direktivy <VirtualHost>, podle toho, co všechno chceme logovat.

Jeden log pro každou doménu

Direktivu přidáme do odpovídajícího VirtualHosta:

<VirtualHost *:80>
    ServerName domain.tld
    ...
    CustomLog /home/www/logs/domain.tld.log combined
</VirtualHost>

Jeden log pro celý server

Přidáme mimo VirtualHost:

# vlastní formát logu, prefixem je jméno VirtualHosta
LogFormat "%{Host}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" cplus
CustomLog /home/www/logs/server.log cplus

V případě této konfigurace musíme Awstats říct o novém formátu logu, což provedeme přímo v konfiguraci awstats.conf úpravou řádky LogFormat:

LogFormat="%virtualname %host %other %logname %time1 %methodurl %code %bytesd %refererquot %uaquot"

Další nastavení

Alias /awstats-icon/ /usr/share/awstats/icon/
<Directory /usr/share/awstats/icon>
    Options None
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

Namapuje adresář s obrázky Awstats do URL adresy /awstats-icon/.

Zpracování

K periodické aktualizaci dat nastavíme cron (pokud již tak distributor neudělal):

*/15 *  * * *   root    /home/bin/awstats_updateall.pl now --excludeconf=awstats.conf > /dev/null 2>&1

Skript awstats_updateall.pl a dalších pár šikovných skriptů nalezneme v adresáři /usr/share/doc/awstats/examples. Tento skript zpracovává všechny konfigurační soubory, takže aktualizuje všechny domény.

Máme-li správně nastavené CGI, což ve výchozí konfiguraci obvykle bývá, nalezneme webový frontend awstats na adrese http:domain.tld/cgi-bin/awstats.pl?con­fig=domain.tld//. Kromě řešení na bázi Perl frontendu a awstats_updateall.pl skriptu je však možné využít awstats_buildstaticpages.pl, který přímo vygeneruje HTML soubory do adresáře zadaného v parametru. Toto řešení převážně využívám na webhostingách, má však tu nevýhodu, že není možné zobrazit statistiky za jiná období a zákazník vždy vidí pouze aktuální měsíc.

Vylepšení

Napsal jsem rewrite, který podstatně zkrášluje adresu a parametr předávaný skriptu /cgi-bin/awstats.pl na webu:

RewriteEngine On
RewriteRule ^/?([^/]+)/$ /cgi-bin/awstats.pl?config=$1 [PT,L,QSA]

Výše zmíněný kód je vhodné aplikovat na určitou subdoménu, např. stats. Statistiky pak nalezneme na adrese http://stats.anotherdomain.tld/domain.tld/.

Statistiky subdomén

Awstats se samozřejmě dá nastavit tak, aby u určité domény logoval i každou subdoménu. Tento přístup kombinuje a upravuje formáty logů popsané výše. Každá subdoména musí mít svůj VirtualHost a definovaný log, v optimálním případě budou logy pro každou doménu zvlášť a v nich spojené logy subdomén s upraveným formátem (viz. jeden log pro celý server).

Štítky: