<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lonewolf Media</title>
	<atom:link href="http://www.lonewolfmedia.se/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lonewolfmedia.se</link>
	<description>Webbutveckling, Linux och Öppen Källkod.</description>
	<lastBuildDate>Sun, 30 Oct 2011 21:36:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Enkel valutakonvertering i PHP</title>
		<link>http://www.lonewolfmedia.se/2011/10/30/enkel-valutakonvertering-i-php/</link>
		<comments>http://www.lonewolfmedia.se/2011/10/30/enkel-valutakonvertering-i-php/#comments</comments>
		<pubDate>Sun, 30 Oct 2011 21:36:31 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programmering]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[konvertering]]></category>
		<category><![CDATA[omvandlare]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[valuta]]></category>
		<category><![CDATA[valutakalkylator]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=447</guid>
		<description><![CDATA[Har haft många järn i elden den senaste tiden, därav dålig uppdateringsfrekvens på bloggen. Bättring lovas framöver! Ett hobbyprojekt jag ägnat mig åt lite på senaste tiden behövde en enkel och pålitlig funktion för att omvandla värdet mellan valutor. Det finns gott om kommersiella API:er som gör detta, och ska funktionen användas i professionella sammanhang [...]]]></description>
			<content:encoded><![CDATA[<p>Har haft många järn i elden den senaste tiden, därav dålig uppdateringsfrekvens på bloggen. Bättring lovas framöver! Ett hobbyprojekt jag ägnat mig åt lite på senaste tiden behövde en enkel och pålitlig funktion för att omvandla värdet mellan valutor. Det finns gott om kommersiella API:er som gör detta, och ska funktionen användas i professionella sammanhang är det nog där man ska leta, men för detta hobbyprojekt fungerade det utmärkt att anropa Googles <a title="Googles valutakalkylator" href="http://www.google.com/finance/converter">valutakalkylator</a>. Funktionen ser ut som följer:</p>
<pre>/**
 * Use currency converter from Google to convert between currencies
 * Usage: currencyConvert(1, "USD", "SEK")
 * Uses str_replace to convert into parsable json
 * Returns value, i.e. "6.55420823" as a string
 */
function currencyConvert($amount, $from, $to) {
	$query	= 'http://www.google.com/ig/calculator?q='.$amount.$from.'=?'.$to;
	$curr 	= file_get_contents($query);
	$wrong	= array('lhs','rhs','error','icc');
	$right	= array('"lhs"','"rhs"','"error"','"icc"');
	$arr	= json_decode(str_replace($wrong, $right, $curr), true);
	return strstr($arr['rhs'], ' ', true);
}

echo currencyConvert(1, "USD", "SEK");</pre>
<p>Funktionen tar som första argument beloppet som ska beräknas följt av valutan som ska omvandlas från och sedan valutan som ska omvandlas till. Dessa valutor skriv i tre bokstäver enligt <a href="http://www.xe.com/iso4217.php">standarden för valutorkoder</a>. Funktionen rensar sedan upp i responssträngen och returnerar slutligen endast beloppet i den nya valutan.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/10/30/enkel-valutakonvertering-i-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Underrättelser till skrivbordet från skript med notify-send</title>
		<link>http://www.lonewolfmedia.se/2011/09/02/underrattelser-till-skrivbordet-fran-sript-med-notify-send/</link>
		<comments>http://www.lonewolfmedia.se/2011/09/02/underrattelser-till-skrivbordet-fran-sript-med-notify-send/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 17:32:39 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Systemadministration]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[chown]]></category>
		<category><![CDATA[error_log]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[fortune]]></category>
		<category><![CDATA[fortune-mod]]></category>
		<category><![CDATA[gnome-session-properties]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[loggfiler]]></category>
		<category><![CDATA[notifications]]></category>
		<category><![CDATA[notify-send]]></category>
		<category><![CDATA[tail]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[underrättelse]]></category>
		<category><![CDATA[underrättelser]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=418</guid>
		<description><![CDATA[notify-send notify-send är ett litet, enkelt och fantastiskt användbart program för att skicka meddelanden från terminalen till skrivbordets system för underrättelser (notifications). Det spelar ingen roll vilken skrivbordsmiljö du använder, och det är inte heller något du behöver ange; notify-send tar hand om det åt dig. Däremot skiljer sig det förstås lite i utseende mellan [...]]]></description>
			<content:encoded><![CDATA[<h2>notify-send</h2>
<p><strong>notify-send</strong> är ett litet, enkelt och fantastiskt användbart program för att skicka meddelanden från terminalen till skrivbordets system för underrättelser (notifications). Det spelar ingen roll vilken skrivbordsmiljö du använder, och det är inte heller något du behöver ange; notify-send tar hand om det åt dig. Däremot skiljer sig det förstås lite i utseende mellan underrättelser i de olika miljöerna. För närvarande använder jag skrivbordsmiljön <strong>Gnome 3</strong> där underrättelserna dyker upp i nedre skärmkanten och ser ut så här:</p>
<p><a href="http://www.lonewolfmedia.se/wp-content/uploads/2011/09/notification2.png"><img class="alignleft size-full wp-image-423" title="Underrättelse" src="http://www.lonewolfmedia.se/wp-content/uploads/2011/09/notification2.png" alt="Underrättelse" width="576" height="47" /></a></p>
<p>Använder du Ubuntu dyker underrättelserna upp i det övre högra hörnet, använder du KDE i det nedre högra. I program utvecklade för skrivbordsmiljö är det vanligt att underrättelser används för att berätta om status och förändringar i systemet eller i program du kör. Ett vanligt exempel är t.ex. en underrättelse om att en nedladdning är klar. Arbetar man både i terminal och i skrivbordsmiljö är det dock knepigt att ha koll på när långdragna processer och skript kör klart på något annat vis än att öppna upp terminalen och själv se efter. Med <strong>notify-send</strong> löser vi det problemet genom att från vårt skript skicka ett meddelande till vår skrivbordsmiljö. Du kan alltså lugnt sitta och surfa medan exempelvis <a title="Rsync lokalt och över SSH" href="http://www.lonewolfmedia.se/2011/07/01/enkel-backup-med-rsync-lokalt-och-over-ssh/">rsync</a> kör och få ett meddelande när det är klart.</p>
<p>Kommandot för ovanstående underrättelse är inte svårare än så här:</p>
<pre>notify-send -t 10000 "Underrättelse" "Ser ut så här!"</pre>
<p>Växeln <strong>-t</strong> använder vi för att ange hur länge underrättelsen ska visas (i millisekunder), i vår fall alltså 10 sekunder. Nästa parameter är rubriken följt av själva meddelandet. Nedan tänkte jag visa två exempel på hur <strong>notify-send</strong> kan användas i praktiken.</p>
<h2>Lyckokakor med notify-send!</h2>
<p>Det första exemplet är kanske roligare än vad det är nyttigt. <strong>Fortune</strong> är ett riktigt klassiskt program för terminalen vars enda uppgift är att skriva ut ett meddelande likt det som finns i lyckokakor (fortune cookies) till terminalen. Meddelandena är ganska varierade, från aforismer till citat och skämt, de flesta med en ganska &#8221;nördig&#8221; betoning. För att använda <strong>fortune</strong> installerar du paketet <strong>fortune-mod</strong> och skriver sedan bara <strong>fortune</strong> för att få en lyckokaka:</p>
<pre>[anders@anders-laptop ~]$ fortune
Never do today what you can put off until tomorrow.</pre>
<p>Visdomsord indeed! Många använder <strong>fortune</strong> för att visa ett &#8221;lycko&#8221;-meddelande till användare då de loggar in, exempelvis över SSH. Vad vi vill göra här är samma sak fast i form av en underrättelse i skrivborsmiljö. För att skicka meddelandet från<strong> fortune</strong> anger vi det som en parameter till <strong>notify-send</strong>:</p>
<pre>notify-send -t 10000 "Lyckokaka" "`fortune`"</pre>
<p><a href="http://www.lonewolfmedia.se/wp-content/uploads/2011/09/message.png"><img class="alignleft size-full wp-image-426" title="Lyckokaka" src="http://www.lonewolfmedia.se/wp-content/uploads/2011/09/message.png" alt="Lyckokaka" width="562" height="135" /></a></p>
<p>Kommandot är i princip identiskt med det vi skrev tidigare. Det enda vi bytt ut är meddelandet som nu istället för en egen text visar resultatet av kommandot <strong>fortune</strong>. Detta åstadkommer vi genom att sätta kommandot <strong>fortune</strong> innanför `-tecken (tecknet kallas &#8221;grav accent&#8221; på svenska) vilket signalerar till <strong>bash</strong> att texten innanför ska ersättas med programmets utskrift och inte texten &#8221;fortune&#8221;. Som en sista touch på det hela byter vi ut den tråkiga ikonen med glödlampan till något lämpligare. Jag hittade <a title="Fortune Cookie" href="http://www.lonewolfmedia.se/wp-content/uploads/2011/09/fc.png">den här bilden</a> på en lyckokaka. Att ange vilken ikon som ska användas gör vi med växeln <strong>-i</strong>:</p>
<pre>notify-send -t 10000 -i "/home/anders/fc.png" "Fortune Cookie" "`fortune`"</pre>
<p><a href="http://www.lonewolfmedia.se/wp-content/uploads/2011/09/message2.png"><img class="alignleft size-full wp-image-434" title="Fortune Cookie med ikon" src="http://www.lonewolfmedia.se/wp-content/uploads/2011/09/message2.png" alt="Fortune Cookie med ikon" width="560" height="90" /></a></p>
<p>Jag bytte också ut texten &#8221;Lyckokaka&#8221; till &#8221;Fortune Cookie&#8221; då alla meddelanden ändå är på engelska och jag föredrar att inte blanda språk. Det sista jag gör nu är att lägga in ovanstående kommando bland skrivbordsmiljöns uppstartsprogram. I <strong>Gnome</strong> gör vi det grafiskt med programmet <strong>gnome-session-properties</strong> men varierar förstås mellan olika skrivbordsmiljöer. Varje gång vi startar om datorn eller loggar in i min skrivborsmiljö får vi nu en lyckokaka i form av en underrättelse!</p>
<h2>Underrättelser från Apaches loggfil</h2>
<p>Ett smart användningsområde för <strong>notify-send</strong> kan vara att bevaka en loggfil och rapportera ändringar och fel som underrättelser på skrivbordet. Det &#8221;klassiska&#8221; sättet att bevaka en loggfil brukar från terminalen vara med kommandot <strong>tail</strong> och växeln <strong>-f</strong> (follow) som printar ut de sista 10 raderna ur en fil och uppdateras allteftersom filen fylls med nya rader. Ägnar vi oss åt exempelvis webbutveckling i skrivbordsmiljö kan det dock vara tidsödande att ständigt växla mellan terminalen och skrivbordet för att kontrollera om Apaches loggfil visar några fel. Ett sätt att slippa det kan vara att skicka ändringarna som <strong>tail -f</strong> registrerar till <strong>notify-send</strong> för att få dem som underrättelser istället.</p>
<p>För att kunna bevaka Apaches loggfil behöver vi antingen ha root-access eller ändra behörigheten på loggfilen så att den kan läsas av en vanlig användare. I en produktionsmiljö, alltså en webbserver som ligger online är det förstås idioti att låta vilken användare som helst få tillgång till loggfilerna. Här är det dock bara en lokal utvecklingsmiljö vi använder oss av, och gissningsvis är webbserverloggarna på min laptop inte av något större intresse ens om någon utomstående fick tillgång till den! I en &#8221;skarp&#8221; miljö används ju dessutom sällan en skrivbordsmiljö på servern, vilket sålunda betyder att dessa instruktioner bara är av användning för utveckling på egen dator! Nåväl, vi börjar därför med att ändra behörighetskraven för katalogen med Apaches loggfiler:</p>
<pre>sudo chown -R anders /var/log/httpd/</pre>
<p>Ovanstående ändrar ägare för katalogen /var/log/httpd inklusive filer däri från användaren root till användaren anders, alltså min användare. Kontrollera att du kan läsa filen /var/log/httpd/error_log genom att skriva &#8221;tail /var/log/httpd/error_log&#8221; utan att använda sudo. Fungerar det kan vi nu fortsätta med vårt kommando som i sin helhet kommer se ut så här:</p>
<pre>tail -n0 -f /var/log/httpd/error_log | while read line; do \
notify-send -t 10000 "Apache error_log:" "$line"; done</pre>
<p>Vi inleder alltså med att anropa programmet <strong>tail</strong> med växeln <strong>-f </strong>för att följa vad som händer i filen /var/log/httpd/error_log. Vad som är nytt här är växeln <strong>-n0</strong>. -n-växeln anger hur många rader från filen som som ska visas i terminalen. I vårt fall vill vi inte ha några rader alls i terminalen då vi  ju istället vill skicka meddelanden till <strong>notify-send</strong>, således <strong>-n0</strong>. Vi låter sedan en loop kontinuerligt läsa av de förändringar som <strong>tail</strong> rapporterar och spara dessa i variabeln <strong>line</strong>. Denna variabel anges sedan som meddelande i kommandot <strong>notify-send</strong>. Programmet kommer alltså att köra tills det avbryts av användaren och lämpar sig därför att köras i en <a title="Hantera processer i bash" href="http://www.lonewolfmedia.se/2011/07/29/kontrollera-processer-i-bash/">bakgrundsprocess</a>.</p>
<p>Även detta kommandot lägger jag till i <strong>gnome-session-properties</strong> för att starta processen varje gång jag loggar in i min skrivbordsmiljö. Uppstår det nu något fel i Apache medan jag sitter och utvecklar och testar webbsidor och php-skript kommer det direkt upp en underrättelse om detta:</p>
<p><a href="http://www.lonewolfmedia.se/wp-content/uploads/2011/09/apache.png"><img class="alignleft size-full wp-image-439" title="Apache error" src="http://www.lonewolfmedia.se/wp-content/uploads/2011/09/apache.png" alt="Apache error" width="560" height="90" /></a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/09/02/underrattelser-till-skrivbordet-fran-sript-med-notify-send/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kontrollera diskutrymme med df och du</title>
		<link>http://www.lonewolfmedia.se/2011/08/31/kontrollera-diskutrymme-med-df-och-du/</link>
		<comments>http://www.lonewolfmedia.se/2011/08/31/kontrollera-diskutrymme-med-df-och-du/#comments</comments>
		<pubDate>Wed, 31 Aug 2011 23:29:50 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Systemadministration]]></category>
		<category><![CDATA[alias]]></category>
		<category><![CDATA[df]]></category>
		<category><![CDATA[diskanvändning]]></category>
		<category><![CDATA[diskutrymme]]></category>
		<category><![CDATA[du]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[systemadministration]]></category>
		<category><![CDATA[tail]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=408</guid>
		<description><![CDATA[En kort introduktion till df och du Då jag ofta har användning av programmen df och du tänkte jag kort introducera dom här med förhoppningen att det också kan vara till nytta för någon annan. Båda programmen används för att kontrollera tillgängligt/upptaget diskutrymme på UNIX-system (båda finns tillgängliga i både Linux och Mac OS X) [...]]]></description>
			<content:encoded><![CDATA[<h2>En kort introduktion till df och du</h2>
<p>Då jag ofta har användning av programmen <strong>df</strong> och <strong>du</strong> tänkte jag kort introducera dom här med förhoppningen att det också kan vara till nytta för någon annan. Båda programmen används för att kontrollera tillgängligt/upptaget diskutrymme på UNIX-system (båda finns tillgängliga i både Linux och Mac OS X) men fungerar på lite olika sätt. Kommandot <strong>df</strong> används för att få en snabb överblick över tillgängliga filsystem och diskanvändningen på dessa. Kommandot <strong>du</strong> används för att lista diskanvändningen i enskilda kataloger och filer.</p>
<h2>df &#8211; visa diskutrymme i filsystem</h2>
<p>Kommandot <strong>df</strong> utan några argument ger på min laptop (med en hårddisk) följande:</p>
<pre>[anders@anders-laptop ~]$ df
Filsystem             1K-block    Använt Tillgängl Anv% Monterat på
rootfs                31244260  18431140  12495796  60% /
udev                   1003096         0   1003096   0% /dev
tmpfs                  1012220      1352   1010868   1% /dev/shm
tmpfs                  1012220       732   1011488   1% /run
/dev/sda3             31244260  18431140  12495796  60% /
tmpfs                  1012220         0   1012220   0% /sys/fs/cgroup
tmpfs                  1012220         0   1012220   0% /media
/dev/sda3             31244260  18431140  12495796  60% /tmp
/dev/sda3             31244260  18431140  12495796  60% /var/tmp
/dev/sda3             31244260  18431140  12495796  60% /home
192.168.0.20:/home   950079616  24739904 877078400   3% /media/b3
192.168.0.8:/Backup  960301840 762754944 197546896  80% /media/Backup
192.168.0.8:/Upload  960301840 762754944 197546896  80% /media/Upload
192.168.0.8:/Public  960301840 762754944 197546896  80% /media/Public</pre>
<p>Här kommer det upp en hel del, och listan är inte helt lätt att tolka om man inte har vanan inne. I första kolumnen listas här alla filsystem som finns monterade för tillfället. Vi ser till exempel att min huvudpartition &#8221;/dev/sda3&#8243; är monterad på &#8221;/&#8221; alltså som root-partition och att denna partition använder 31244260 bytes och har 12495796 bytes till förfogande samt att 60% av utrymmet på disken/partitonen används. Längst ner ser vi också vilka filsystem som är monterade över nätverket, i det här fallet genom <strong>nfs</strong> (network file system). <strong>df</strong> listar &#8221;riktiga&#8221; filsystem lokalt eller över nätverk, såväl som temporära och virtuella filsystem. Normalt sett har vi ingen större glädje av att veta status på de två sistnämnda. Inte heller är byte en särskilt meningsfull måttenhet i dagens datorvärld.</p>
<p>Vi gör därför ett försök att rensa upp lite i listan för att få ett för oss mer användbart resultat. <strong>df</strong> accepterar ett flertal växlar för att påverka vad som listas och hur. Den kanske enklaste och mest använda är växeln <strong>-h</strong> som står för &#8221;human readable&#8221; och omvandlar bytes till mer lättlästa megabytes (M), gigabytes (G), osv. <strong>df -h</strong> ger följande:</p>
<pre>[anders@anders-laptop ~]$ df -h
Filsystem          Storlek Anvnt Tillg Anv% Monterat på
rootfs                 30G   18G   12G  60% /
udev                  980M     0  980M   0% /dev
tmpfs                 989M  1,4M  988M   1% /dev/shm
tmpfs                 989M  732K  988M   1% /run
/dev/sda3              30G   18G   12G  60% /
tmpfs                 989M     0  989M   0% /sys/fs/cgroup
tmpfs                 989M     0  989M   0% /media
/dev/sda3              30G   18G   12G  60% /tmp
/dev/sda3              30G   18G   12G  60% /var/tmp
/dev/sda3              30G   18G   12G  60% /home
192.168.0.20:/home    907G   24G  837G   3% /media/b3
192.168.0.8:/Backup   916G  728G  189G  80% /media/Backup
192.168.0.8:/Upload   916G  728G  189G  80% /media/Upload
192.168.0.8:/Public   916G  728G  189G  80% /media/Public</pre>
<p>Genast känns listan betydligt enklare att överblicka. Återstår gör då att exkludera de filsystem från listan som vi inte är intresserade av att följa. I mitt fall är det alla filsystem som används av systemet och inte direkt av mig och dessa är ovan <strong>rootfs</strong>, <strong>udev</strong> och <strong>tmpfs</strong>. För att ekludera filsystem från listan använder vi växeln <strong>-x</strong> följt av filsystemstypen. För att få reda på vilka filsystemstyper de olika partionerna tillhör använder vi växeln <strong>-T</strong>:</p>
<pre>[anders@anders-laptop ~]$ df -h -T
Filsystem      Typ Storlek Anvnt Tillg Anv% Monterat på
rootfs      rootfs     30G   18G   12G  60% /
udev      devtmpfs    980M     0  980M   0% /dev
tmpfs        tmpfs    989M  1,4M  988M   1% /dev/shm
tmpfs        tmpfs    989M  732K  988M   1% /run
/dev/sda3     ext4     30G   18G   12G  60% /
tmpfs        tmpfs    989M     0  989M   0% /sys/fs/cgroup
tmpfs        tmpfs    989M     0  989M   0% /media
/dev/sda3     ext4     30G   18G   12G  60% /tmp
/dev/sda3     ext4     30G   18G   12G  60% /var/tmp
/dev/sda3     ext4     30G   18G   12G  60% /home
192.168.0.20:/home
               nfs    907G   24G  837G   3% /media/b3
192.168.0.8:/Backup
               nfs    916G  728G  189G  80% /media/Backup
192.168.0.8:/Upload
               nfs    916G  728G  189G  80% /media/Upload
192.168.0.8:/Public
               nfs    916G  728G  189G  80% /media/Public</pre>
<p>Vi ser nu en ny kolumn som listar Typ. Det första filsystem jag inte var intresserad av att visa var <strong>rootfs</strong> som är av typen <strong>rootfs</strong>. Den andra var <strong>udev</strong> som listas som typen <strong>devtmpfs</strong> och den tredje var <strong>tmpfs</strong> som också är av typen <strong>tmpfs</strong>. Då kan vi alltså börja använda växeln <strong>-x</strong> för att exkludera oönskade filsystemstyper:</p>
<pre>[anders@anders-laptop ~]$ df -h -x rootfs -x devtmpfs -x tmpfs
Filsystem          Storlek Anvnt Tillg Anv% Monterat på
/dev/sda3              30G   18G   12G  60% /
/dev/sda3              30G   18G   12G  60% /tmp
/dev/sda3              30G   18G   12G  60% /var/tmp
/dev/sda3              30G   18G   12G  60% /home
192.168.0.20:/home    907G   24G  837G   3% /media/b3
192.168.0.8:/Backup   916G  728G  189G  80% /media/Backup
192.168.0.8:/Upload   916G  728G  189G  80% /media/Upload
192.168.0.8:/Public   916G  728G  189G  80% /media/Public</pre>
<p>Aningen enklare att överblicka än tidigare, eller hur? Däremot ganska krångligt att skriva ut hela kommandot med växlar varje gång vi bara vill kolla tillgängligt diskutrymme. Då det är såhär jag alltid vill att kommandot <strong>df</strong> ska lista filsystem åt mig lägger jag till kommandot med alla växlar som ett <strong>alias</strong> för &#8221;df&#8221;:</p>
<pre>[anders@anders-laptop ~]$ alias df='df -h -x rootfs -x devtmpfs -x tmpfs'</pre>
<p>Nu kommer det räcka med att skriva bara &#8221;df&#8221; för att använda programmet med samtliga växlar vi valt att nyttja. På så vis slipper vi framöver komma ihåg alla filsystemstyper vi inte är intresserade av utan skriver bara &#8221;df&#8221; som vanligt och får automagiskt programmet att visa vad vi vill se! Vi har nu sparat vårt alias i minnet. Detta kommer dock försvinna när vi startar om datorn eller loggar ut vår användare. Det sista vi gör är därför att spara vårt alias på hårddisken så att det automatiskt läses in varje gång vi loggar in. Det gör vi genom att klistra in kommandot (precis som det skrevs ut i terminalen) i filen .bashrc som ligger i vår hemkatalog. Ligger den inte där kan du själv skapa den. Nu har vi framöver ett användarvänligt <strong>df</strong> till vår nytta!</p>
<h2>du &#8211; visa diskanvändning i kataloger och filer</h2>
<p>Kommandot<strong> du</strong> använder vi när vi vill veta exakt vilka kataloger (och om vi vill, filer) som tar upp plats på disken.  Kommandot utan några växlar listar som standard alla kataloger i den nuvarande katalogen och skriver ut hur många bytes katalogen (med underkataloger och filer) använder. Växeln <strong>-a</strong> (all) använder vi om vi utöver kataloger även vill visa filer. Även här kan vi använda växeln <strong>-h</strong> (human readable) för att få en mer lättbegriplig lista:</p>
<pre>[anders@anders-laptop HTC Desire]$ du -h
47M	./20-08-2011
76M	./24-4-2011
66M	./23-11-2010
49M	./12-08-2011
30M	./03-01-2011
134M	./Första bilderna
16M	./28-08-2011
125M	./24-07-2011
539M	.</pre>
<p>Ovan kör jag kommandot <strong>du -h</strong> i katalogen &#8221;HTC Desire&#8221; (som innehåller alla bilder jag tagit med min mobiltelefon). Totalt är det 8 underkataloger. Den sista raden är en sammanfattning av katalogens totala storlek, det vill säga summan av samtliga underkataloger. Ofta är det bara den siffran vi är intresserade av och kan då använda växeln -s (summary) för just det ändamålet:</p>
<pre>[anders@anders-laptop HTC Desire]$ du -sh
539M	.</pre>
<p>Skriver vi t.ex. &#8221;du -sh ~&#8221; får vi veta hur mycket utrymme hela vår hemkatalog tar upp. Tar vi bort växeln -s får vi veta exakt vilka kataloger som tar upp mest plats. Användbart när du vill jaga de största utrymmestjuvarna.</p>
<p>Avslutningsvis, en elegant variant vi kan använda för att hitta de största katalogerna är att skicka programmets output vidare till kommandot <strong>sort</strong> för att visa katalogerna i storleksordning. I kommandot nedan skickar vi dessutom den sorterade listan till kommandot <strong>tail</strong> för att begränsa listan till de 10 största katalogerna i vår hemkatalog:</p>
<pre>[anders@anders-laptop HTC Desire]$ du ~ | sort -n | tail<span class="Apple-style-span" style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px; white-space: normal;"> </span></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/08/31/kontrollera-diskutrymme-med-df-och-du/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Geopositionering i PHP och Javascript</title>
		<link>http://www.lonewolfmedia.se/2011/08/22/geopositionering-i-php-och-javascript/</link>
		<comments>http://www.lonewolfmedia.se/2011/08/22/geopositionering-i-php-och-javascript/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 11:57:49 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webb]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[geo location]]></category>
		<category><![CDATA[geo tracking]]></category>
		<category><![CDATA[geopositionering]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[webb]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=376</guid>
		<description><![CDATA[Geopositionering Geopositionering (från engelskans &#8221;geo location&#8221; eller &#8221;geo tracking&#8221;) har de senaste åren blivit allt populärare i takt med att våra datorvanor blivit allt mer mobila. Mer eller mindre alla stora sidor använder någon form av geopositionering för att bestämma var användaren kommer från för att på så vis kunna anpassa innehållet, språket eller marknadsföringen [...]]]></description>
			<content:encoded><![CDATA[<h2>Geopositionering</h2>
<p>Geopositionering (från engelskans &#8221;geo location&#8221; eller &#8221;geo tracking&#8221;) har de senaste åren blivit allt populärare i takt med att våra datorvanor blivit allt mer mobila. Mer eller mindre alla stora sidor använder någon form av geopositionering för att bestämma var användaren kommer från för att på så vis kunna anpassa innehållet, språket eller marknadsföringen efter det. Även utan att anpassa din sida efter besökarens geografiska position kan det förstås vara intressant att se var dina besökare kommer ifrån.</p>
<p>Det finns i grunden två typer av geopositionering; Antingen gör man det på serversidan med hjälp av besökarens IP-adress och en databas som länkar IP-adresser med geografiska positioner. Det andra alternativet är att göra det i din besökares webbläsare genom Javascript. Följande artikel ger en snabb inblick i båda metoder.</p>
<h2>Geopositionering baserat på IP-adress</h2>
<p>Fördelen med denna metoden är att du alltid har tillgång till dina besökares IP-adress, varför inte använda den till något? Nackdelen med att geopositionera efter IP-nummer är att metoden är minst sagt opålitlig. Informationen är normalt inte mer exakt än t.ex. vilken stad besökaren finns i. Det finns dessutom ingen som helst garanti för att den informationen du får är korrekt då databasen som mappar IP-nummer till geografisk position kan vara både utdaterad eller direkt felaktig.</p>
<p>Det finns både fria och kommersiella databaser att tillgå för detta ändamål, där de som kostar pengar rimligtvis bör ge något exaktare resultat(?), men fortfarande utan garantier. Å andra sidan är det ju också rätt skönt att ens position inte går att spåra exakt på ens IP-adress, eller hur? Syftet med geopositionering är förstås inte att ta reda på vilken exakt fysisk position din besökare finns på utan mer att kunna se större trender och mönster baserat på dina besökares geografiska plats. Kommer t.ex. 95% av besökarna till din webbshop från Stockholmsområdet är det kanske inte i Göteborg du ska öppna din första fysiska butik!</p>
<h2>Geopositionering från webbläsaren</h2>
<p>Geopositionering från webbläsaren används flitigt av framförallt sociala medier så som Twitter, Google+ m.fl. När du använder geopositionering från webbläsaren är det användaren själv som väljer huruvida den vill dela med sig sin geografiska position eller inte, normalt sett genom en liten ruta som dyker upp och berättar att webbsidan vill använda din geografiska position och ber dig godkänna eller avslå denna begäran. Detta är helt enligt specifikationerna för Javascripts Geolocation API och är inget som normalt kan åsidosättas.</p>
<p><a href="http://www.lonewolfmedia.se/wp-content/uploads/2011/08/tracking.png"><img class="alignleft size-full wp-image-393" title="tracking" src="http://www.lonewolfmedia.se/wp-content/uploads/2011/08/tracking.png" alt="Geopositionering" width="421" height="37" /></a></p>
<p>&#8221;Nackdelen&#8221; är således självklart att du inte kan tvinga dina besökare att ange sin fysiska position. Fördelen är att metoden är betydligt mer exakt än positionering baserat på IP-nummer! Då metoden använder sig av både WiFi-positionering och GPS (om tillgängligt) går det oftast att få geografiskt position så exakt som adress och trappuppgång. Viktigt är förstås att denna information används på ett sätt som användaren är informerad om. De flesta hade förmodligen blivit ganska irriterade om det började dyka upp reklam i brevlådan efter att de angett sin geografiska position på din sida! Geopositionering från webbläsaren ska alltså främst ses som något som förbättrar upplevelsen för dina besökare.</p>
<p>Nedan tar vi en titt på hur båda metoder implementeras i praktiken.</p>
<h2>Geopositionering från IP-adress på serversidan med PHP</h2>
<p>Det finns lite olika metoder att använda i PHP när det kommer till att geopositionera besökare baserat på deras IP-adress. Metoden vi använder här baserar sig på paketet <a title="GeoIP PHP" href="http://www.php.net/manual/en/book.geoip.php">GeoIP</a> som är enkelt att hämta i de flesta linuxdistributioners pakethanterare. I Fedora heter paketet <strong>php-pecl-geoip</strong>. Du behöver dessutom installera C-biblioteket <strong>GeoIP</strong>. Använder du inte Linux finns <a title="GeoIP installation" href="http://www.php.net/manual/en/geoip.installation.php">installationsinstruktioner här</a>.</p>
<p>Paketet bygger på en öppen databas som tillhandahålls av företaget <a title="MaxMind" href="http://www.maxmind.com/">MaxMind</a>. Det går även att betala för en komersiell databas och fler funktioner. Nåväl, så fort installationen är klar kan du börja använda de inkluderade funktionerna för geopositionering. De flesta funktioner tar ett värdnamn eller ip-nummer som argument, vilket är enkelt fixat med den globala variabeln $_SERVER['REMOTE_ADDR']. I koden nedan använder vi sedan ip-numret i funktionen geoip_record_by_name, som returnerar en vektor med samlad information om ip-numrets geoposition:</p>
<pre>$ip = $_SERVER['REMOTE_ADDR'];
$geodata = geoip_record_by_name($ip);

print_r($geodata);</pre>
<p>Här stöter jag dock på patrull i form av en <a title="GeoIP Varning" href="http://www.lonewolfmedia.se/wp-content/uploads/2011/08/geoipvarning.png">varning</a>: Databasen GeoIPCity.dat verkar inte finnas tillgänglig. Nåväl, efter lite sökande hittar vi <a title="GeoIP installation" href="http://www.maxmind.com/app/installation?city=1">instruktioner</a> för att hämta hem den:</p>
<pre>wget -N -q http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
mv GeoLiteCity.dat /usr/share/GeoIP/GeoIPCity.dat</pre>
<p>Nu har vi laddat hem databasen och flyttat den till rätt plats. Nu skriver ovanstående kod ut något i stil med vektorn nedan, förstås beroende av var ip-numret härstammar:</p>
<pre>Array (
[continent_code] =&gt; EU
[country_code] =&gt; SE
[country_code3] =&gt; SWE
[country_name] =&gt; Sweden
[region] =&gt; 26
[city] =&gt; Stockholm
[postal_code] =&gt;
[latitude] =&gt; 59.333301544189
[longitude] =&gt; 18.049999237061
[dma_code] =&gt; 0
[area_code] =&gt; 0
)</pre>
<p>Som synes har vi en hel del användbar information endast baserat på IP-adressen. Det är lätt att tänka att latitud/longitud-kordinaterna ger en exakt position. Det handlar dock bara om uppskattningar, så ta dem med en nypa salt. Testa gärna med din egen IP-adress för att se hur exakt resultat du får! Vill du bara testa funktionen utan att skriva kod finns en <a title="MaxMind geoposition online demo" href="http://www.maxmind.com/app/locate_my_ip">demo online här</a>.</p>
<h2>Geopositionering från webbläsaren med Javascript</h2>
<p>För att kunna använda geopositionering från webbläsaren måste vi börja med att kontrollera att webbläsaren har stöd för detta. Det gör vi genom att kolla efter navigator.geolocation:</p>
<pre>if (navigator.geolocation)
{
...
}</pre>
<p>Såvida du inte använder en antik webbläsare bör det inte vara några problem. När vi väl bestämt att vår användare har tillgång till Javascripts Geolocation API är det primärt <a title="Geolocation API" href="http://dev.w3.org/geo/api/spec-source.html#geolocation">tre funktioner</a> vi använder för att spåra geografisk position:</p>
<ul>
<li>getCurrentPosition</li>
<li>watchPosition</li>
<li>clearWatch</li>
</ul>
<p>getCurrentPosition gör precis vad namnet antyder. Funktionen tar tre parametrar varav den första är en s.k. callback-funktion som kommer att anropas om funktionen lyckades. Den andra parametern är en motsvarande funktion om du vill hantera vad som händer om funktionen <em>inte</em> lyckas. Den tredje parametern använder vi om vi vill ställa in exakt hur positionen ska mätas. I det här exemplet kommer jag att förutsätta att funktionen lyckas med vad den ska och därför endast använda den första parametern, som alltså är ett anrop till en annan funktion, i mitt fall funktionen showPosition:</p>
<pre>if (navigator.geolocation) {

	navigator.geolocation.getCurrentPosition(showPosition);

}

function showPosition(position) {

	console.log('latitude: ' + position.coords.latitude + ' ');
	console.log('longitude: ' + position.coords.longitude);

}</pre>
<p>Ovan anropar vi alltså funktionen getCurrentPosition och vid lyckat resultat anropar vi funktionen showPosition. Callbackfunktionen som anropas av getCurrentPosition blir automatiskt tildelad ett <a title="Geolocation API position object" href="http://dev.w3.org/geo/api/spec-source.html#position">positionsobjekt</a> som vi sedan kan använda oss av inuti vår funktion. Vår funktion, här döpt showPosition gör som ni ser inte mer än att skriva ut koordinaterna för latitud och longitud i webbläsarens javascriptkonsol. Ett populärt användningsområde är förstås att koppla ihop resultatet med ett yttre API, t.ex. <a title="Google Maps API" href="http://code.google.com/intl/sv-SE/apis/maps/documentation/javascript/">Google Maps</a>. Det sparar vi till ett senare inlägg!</p>
<p>Återstår gör då de två andra funktionerna, watchPosition och clearWatch. watchPosition fungerar på samma sätt som Javascripts inbyggda timerfunktion setInterval, och uppdaterar med jämna mellanrum den geografiska positionen. Detta används dels för att det kan behövas fler försök att exakt bestämma någons position men också för att användaren ju kan röra på sig under tiden den besöker din sida! Precis som watchPosition används som Javascripts inbyggda setInterval används clearWatch precis som Javascripts inbyggda clearInterval. I övrigt fungerar funktionen watchPosition på samma vis som getCurrentPosition:</p>
<pre>if (navigator.geolocation) {

	positionT = navigator.geolocation.watchPosition(showPosition);

}

function showPosition(position) {

	console.log('updated latitude: ' + position.coords.latitude + ' ');
	console.log('updated longitude: ' + position.coords.longitude);

}</pre>
<p>Nu har vi förhoppningsvis uppnått en lyckad positionering och avslutar med att stänga av timern för positionering:</p>
<pre>navigator.geolocation.clearWatch(positionT);</pre>
<h2>Sammanfattning</h2>
<p>Som förhoppningsvis framgått av den här korta introduktionen krävs det ingen större ansträngning för att använda geopositionering varken på serversidan eller i webbläsaren. Hur man sedan väljer att använda resultatet är förstås det som är viktigast, och där finns det gott om möjligheter. Jag tänkte i ett kommande inlägg koppla ihop vår geopositionering med Google Maps API, vilket är ett vanligt användningsområde. Har du idéer eller tips om roliga användningsområden så skriv gärna en kommentar!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/08/22/geopositionering-i-php-och-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hantera processer i bash</title>
		<link>http://www.lonewolfmedia.se/2011/07/29/kontrollera-processer-i-bash/</link>
		<comments>http://www.lonewolfmedia.se/2011/07/29/kontrollera-processer-i-bash/#comments</comments>
		<pubDate>Fri, 29 Jul 2011 16:23:01 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Systemadministration]]></category>
		<category><![CDATA[&]]></category>
		<category><![CDATA[bakgrundsprocesser]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[bg]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[fg]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[ps]]></category>
		<category><![CDATA[Red Hat]]></category>
		<category><![CDATA[systemadministration]]></category>
		<category><![CDATA[tail]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=362</guid>
		<description><![CDATA[Introduktion till processer i bash Varje kommando du skriver in i bash startar en egen process. När du skriver t.ex. &#8221;ls&#8221; för att lista innehållet i en katalog startar bash en separat process för det och avslutar den sedan direkt när kommandot utförts. Oftast är det inget man behöver ägna någon särskild tankemöda då de [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduktion till processer i bash</h2>
<p>Varje kommando du skriver in i bash startar en egen process. När du skriver t.ex. &#8221;ls&#8221; för att lista innehållet i en katalog startar bash en separat process för det och avslutar den sedan direkt när kommandot utförts. Oftast är det inget man behöver ägna någon särskild tankemöda då de flesta kommandon och script man anropar exekveras snabbare än man hinner reagera.  Förr eller senare kan det dock dyka upp kommandon eller script som antingen tar lång tid för att de behandlar en stor mängd data eller för att kommandot eller scriptet till sin natur bör köra under en längre tid, kanske för att samla in information om systemet medan det körs. Ett exempel på ett sådant kommando kan t.ex. vara:</p>
<p><code># tail -f /var/log/httpd/error_log</code></p>
<p>Kommandot <strong>tail</strong> gör som du kanske vet inte mycket mer än att skriva ut de sista 10 raderna ur en textfil på skärmen. Med parametern <strong>-f</strong> (follow) fortsätter <strong>tail</strong> att bevaka filen (som i det här fallet är Apaches loggfil för felmeddelanden; /var/log/httpd/error_log) och skriver ut förändringar till skärmen direkt då de upptäcks. Således ett mycket användbart kommando för att bevaka filer som förändras kontinuerligt. Ett problem med ovanstående kommando är dock att då det fortsätter köra kommer vi inte kunna göra någonting annat förrän kommandot antingen avbryts av oss eller avslutar på naturlig väg. Ett sätt att lösa det på kan förstås vara att öppna en separat terminal för just den processen och sedan växla till den terminalen när vi vill se vad som händer i vår loggfil.</p>
<h2>Att köra en process i bakgrunden</h2>
<p>En annan metod är att låta processen köra i bakgrunden och endast &#8221;lyfta fram&#8221; den till förgrunden då vi vill veta vad som händer. För att starta ett kommando i bakgrunden lägger vi bara till ett &#8221;&amp;&#8221;-tecken efter kommandot och eventuella parametrar:</p>
<p><code># tail -f /var/log/httpd/error_log &amp;</code></p>
<p>Resultatet blir precis som innan att vi kommer att se de tio sista raderna ur loggfilen listade. Ovanför dessa kommer vi dock nu att se något i stil med:</p>
<p><code>[1] 9868</code></p>
<p>Bash har nu skapat ett separat &#8221;jobb&#8221; för vårt kommando och givit det ett identifikationsnummer , i det här fallet 1. Nästa siffra, 9868, är operativsystemets processid (pid). Siffrorna kommer förstås vara annorlunda på din dator. Vi har nu två nummer att använda för att identifiera vår process. Men var tog prompten vägen? Tryck på Enter ytterligare en gång för att flytta processen till bakgrunden och lyfta fram prompten till förgrunden.</p>
<h2>Lista processer i bakgrunden med jobs och ps</h2>
<p>Till synes är allting nu som tidigare, men vårt kommando ligger fortfarande och kör i bakgrunden. För att lista de jobb vi startat skriver vi kort och gott &#8221;jobs&#8221;:</p>
<pre>[root@anders-laptop anders]# jobs
[1]+ Kör tail -f /var/log/httpd/error_log &amp;</pre>
<p>För att se vilka <em>processer</em> som körs för närvarande använder vi kommandot <strong>ps</strong> (process status):</p>
<pre>[root@anders-laptop ~]# ps
PID TTY TIME CMD
9693 pts/0 00:00:00 su
9698 pts/0 00:00:00 bash
9868 pts/0 00:00:00 tail
9877 pts/0 00:00:00 ps</pre>
<h2></h2>
<h2>Flytta processer med fg och bg</h2>
<p>För att flytta fram en process till förgrunden använder vi kommandot <strong>fg</strong> följt av jobbnumret:</p>
<pre>[root@anders-laptop anders]# fg 1
tail -f /var/log/httpd/error_log</pre>
<p>En alternativ syntax för att göra samma sak är att använda ett procenttecken följt av jobbnumret. Kommandot ovan kan alltså lika väl skrivas &#8221;%1&#8243;. Processen kommer nu upp och syns på skärmen. För att åter flytta processen till bakgrunden trycker vi [CTRL+Z] för att först stoppa processen (suspend). Sedan använder du kommandot bg för att starta upp processen i bakgrunden igen:</p>
<pre>[root@anders-laptop anders]# bg 1
[1]+ tail -f /var/log/httpd/error_log &amp;</pre>
<p>Observera att om du endast har stoppat en enda process behöver du inte ange något jobbnummer.</p>
<h2>Avsluta process med kill</h2>
<p>En process som körs i förgrunden kan oftast avslutas med tangentkombinationen CTRL+C.  Vi kan när som helst välja att avsluta en process i bakgrunden genom kommandot <strong>kill</strong>. Det går bra att ange både jobbid eller processid som parameter. Standard är dock processid, och vill vi hellre ange jobbid gör vi det med prefixet %:</p>
<p><code>[root@anders-laptop ~]# kill 9868 #alternativt "kill %1"</code></p>
<h2>Sammanfattning</h2>
<p>Ovan är tänkt som en kortfattad introduktion till processhantering i bash. Vill du veta mer om hur processer fungerar i UNIX-miljö finns en bra introduktion på <a title="Wikipedia: Job Control (Unix)" href="http://en.wikipedia.org/wiki/Job_control_(Unix)">Wikipedia</a>, samt förstås bash:s <a title="Job control, bash" href="http://www.faqs.org/docs/bashman/bashref_77.html">egna manual</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/07/29/kontrollera-processer-i-bash/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimera bilder för webben i Linux</title>
		<link>http://www.lonewolfmedia.se/2011/07/22/optimera-bilder-for-webben-i-linux/</link>
		<comments>http://www.lonewolfmedia.se/2011/07/22/optimera-bilder-for-webben-i-linux/#comments</comments>
		<pubDate>Fri, 22 Jul 2011 15:58:39 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Optimering]]></category>
		<category><![CDATA[Systemadministration]]></category>
		<category><![CDATA[Webb]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[automatisering]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[incron]]></category>
		<category><![CDATA[jpegoptim]]></category>
		<category><![CDATA[LAMP]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[optimering]]></category>
		<category><![CDATA[optipng]]></category>
		<category><![CDATA[skript]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=306</guid>
		<description><![CDATA[Nedanstående är första delen av en serie artiklar med temat &#8221;Optimera din webbplats&#8221;. Serien utgår från LAMP (Linux Apache MySQL PHP) som plattform, men de flesta tekniker är förstås tillgängliga universellt. Vi börjar med en av de mest självklara och enkla optimeringsåtgärderna, att optimera de bilder vi presenterar. Förlustfri Optimering De två bilderna ovan är [...]]]></description>
			<content:encoded><![CDATA[<p>Nedanstående är första delen av en serie artiklar med temat &#8221;Optimera din webbplats&#8221;. Serien utgår från LAMP (Linux Apache MySQL PHP) som plattform, men de flesta tekniker är förstås tillgängliga universellt. Vi börjar med en av de mest självklara och enkla optimeringsåtgärderna, att optimera de bilder vi presenterar.</p>
<h2>Förlustfri Optimering</h2>
<p><a href="http://www.lonewolfmedia.se/wp-content/uploads/2011/07/tux.png"><img class="alignnone size-full wp-image-339" title="Innan optimering" src="http://www.lonewolfmedia.se/wp-content/uploads/2011/07/tux.png" alt="Tux innan optimering" width="280" height="307" /></a><a href="http://www.lonewolfmedia.se/wp-content/uploads/2011/07/tuxo.png"><img class="alignnone size-full wp-image-341" title="Efter Optimering" src="http://www.lonewolfmedia.se/wp-content/uploads/2011/07/tuxo.png" alt="Tux efter optimering" width="280" height="307" /></a></p>
<p>De två bilderna ovan är identiska  till både utseende och kvalitet. Bilden till höger har dock optimerats med <strong>optipng</strong> och är därför 11% mindre till storlek (datamängd). Den högra pingvinen har optimerats med förlustfri komprimering vilket innebär att ingen synlig data förändrats. I den här introduktionen använder vi endast förlustfri optimering. Det kan ibland vara berättigat att komprimera bilder ytterligare med mer eller mindre synbara förluster som resultat, men att optimera utan försämrat resultat är alltid ett första steg. Att inte göra det är slöseri med både din och andras bandbredd och tid!</p>
<h2>Varför optimera?</h2>
<p>Optimering gör förstås störst skillnad om du har hög trafik till din sida. Det kan tyckas onödigt att skala bort några enstaka kilobytes här och där om din sida inte besöks av fler än några stycken om dagen, och till viss del stämmer det väl också, men det finns faktiskt skäl till att optimera redan från början:</p>
<ul>
<li>Sökmotorer premierar snabba sidor.</li>
<li>En snabb sida är roligare att besöka. Flera undersökningar från bland annat Amazon visar att en sidas responstid står direkt i proportion till hur länge besökare/kunder stannar kvar och om de återkommer eller ej.</li>
<li>Det kommer bli mycket mer abete att optimera din sida i efterhand.</li>
<li>Ligger din sida på ett webbhotell har du ofta en begränsning i hur mycket data du får lagra, samt hur mycket bandbredd din sida får omsätta per månad.</li>
<li>Det är roligt att ständigt förbättra sin skapelse!</li>
</ul>
<h2>Jpegoptim</h2>
<p>Programmet <strong>jpegoptim</strong> använder en förlustfri kompressionsalgoritm som rekommenderas (och får man anta, används) av inga mindre än <a title="jpegoptim hos Google" href="http://code.google.com/intl/sv-SE/speed/page-speed/docs/payload.html#CompressImages">Google</a>. Använder du Ubuntu finns paketet <strong>jpegoptim</strong> direkt att hämta med apt-get. För Fedora finns inget färdigt paket, och eftersom det är Fedora jag använder för tillfället var jag nödgad att gå den lite längre vägen och kompilera programmet själv.</p>
<p>Laddade först ner senaste versionen (för stunden 1.2.4) från <a title="jpegoptim" href="http://www.kokkonen.net/tjko/projects.html">programmets egna sida</a>. Programmet kräver att utvecklingsfilerna för <strong>libjpeg</strong> finns installerade. Började därför först med att installera dessa, som på fedora heter <strong>libjpeg-turbo-devel</strong>. Sedan var det bara att packa upp programmet och kompilera det:</p>
<pre>./configue
make
make strip
make install</pre>
<p>Proceduren torde se liknande ut även på andra plattformar där färdiga paket saknas, så som Mac OS X. Programmet kommer med en rad möjligheter för kompression, såväl förlustfri som med förluster. Då jag inte vill försämra kvaliteten på bilderna är det förlustfri som gäller, och det får vi med växeln <strong>&#8211;strip-all</strong>:</p>
<pre>[anders@anders-laptop ~]$ jpegoptim --strip-all DSC_0055.JPG
DSC_0055.JPG 3008x2000 24bit  [OK] 2525257 --&gt; 2438219 bytes (3.45%), optimized.</pre>
<p>Som synes blev det i det här fallet ingen dramatiskt förminskning av bildens storlek. Men 3.45% är förstås bättre än ingenting, framför allt som vi inte försämrat bildens kvalitet! Hur mycket data som kan skalas bort beror på flera faktorer i bilden, men normalt brukar det röra sig mellan 2-20%. Enkelt uttryckt så är det lättare att få bra resultat med enkla bilder med mindre detaljer och färger än t.ex. ett foto.</p>
<h2>Optipng</h2>
<p>Optipng är nästa program i ordningen och som namnet ger en vag ledtråd om är det specialiserat på bilder i PNG-formatet. Mer detaljerad information om <strong>optipng</strong> hittar du på <a title="optipng" href="http://optipng.sourceforge.net/">programmets webbplats</a>. Programmet används normalt så här:</p>
<pre>[anders@anders-laptop tmp]$ optipng -o7 ~/kylskapmini.png
OptiPNG 0.6.4: Advanced PNG optimizer.
Copyright (C) 2001-2010 Cosmin Truta.

** Processing: /home/anders/kylskapmini.png
560x314 pixels, 3x8 bits/pixel, RGB
Input IDAT size = 73786 bytes
Input file size = 74004 bytes

Trying:
  zc = 9  zm = 9  zs = 0  f = 0		IDAT size = 56020
  zc = 3  zm = 9  zs = 0  f = 0		IDAT size = 53390
  zc = 3  zm = 9  zs = 1  f = 0		IDAT size = 53390

Selecting parameters:
  zc = 3  zm = 9  zs = 1  f = 0		IDAT size = 53390

Output IDAT size = 53390 bytes (20396 bytes decrease)
Output file size = 53500 bytes (20504 bytes = 27.71% decrease)</pre>
<p>Som synes på sista raden fick vi alltså en förminskning på nästan 28% utan bildförsämring! Växeln -oX där X är ett nummer mellan 1-7 kan användas om man själv vill bestämma hur hårt programmet ska anstränga sig för att optimera din bild. Har du ett stort bildbibliotek får du vara beredd på att en optimering med -o7 kan ta en bra stund. Annars finns ingen anledning att  inte optimera maximalt.</p>
<h2>Automatisk optimering av uppladdade bilder</h2>
<p>Lättja är en grundpelare i all systemadministration. Istället för att manuellt optimera varje enskild bild med verktygen ovan vore det väl skönt om vi kunde automatisera processen? Optimalt hade det ju varit om vi bara kunde ladda upp våra bildfiler som vanligt och låta servern optimera dom utan att vi behövde lyfta ett finger. Det finns som alltid i Linux olika sätt att lösa ett sådant problem, men i det här exemplet använder jag det utmärkta programmet <strong>incron</strong>.</p>
<h2>Bevaka en katalog med incron</h2>
<p>I UNIX-system och dess derivat är <strong>cron</strong> ett system för att schemalägga processer till valda tidpunkter och intervaller. Programmet <strong>incron</strong> bygger på samma princip (och använder samma syntax) men istället för att bevaka klockslag och datum bevakar <strong>incron</strong> förändringar i kataloger. Du väljer själv vilka förändringar du vill bevaka, men i vårt fall vill vi bara se när en ny fil anländer i vår katalog.</p>
<p>Börja med att installera (yum install, apt-get install, etc) <strong>incron</strong>. Lägg sedan till de användare som ska använda <strong>incron</strong> i filen incron.allow som du hittar (eller skapar) i /etc/incron.d/. Starta sedan incron med kommandot &#8221;service incrond start&#8221;. Det som återstår nu är att välja vilken katalog vi vill bevaka och vad som ska hända när en ny fil anländer till katalogen. För att ställa in de reglerna använder vi kommandot:</p>
<p><code>incrontab -e</code></p>
<p>Detta öppnar en editor (vilken bestämmer du i /etc/incron.conf) för redigering av regler för<strong> incron</strong>. Syntaxen för den här filen känner du igen om du jobbat med <strong>crontab</strong> tidigare, annars är den som följer:</p>
<p><code>&lt;katalog&gt; &lt;händelse&gt; &lt;kommando&gt;</code></p>
<p>Exakt vilka händelser du kan bevaka hittar du i manualsidan för incrontab (och en bra guide online <a title="incron guide" href="http://www.howtoforge.com/triggering-commands-on-file-or-directory-changes-with-incron">här</a>), och du kan separera flera händelser med ett kommatecken. I vårt fall vill vi veta när nya filer skapats i vår katalog eller flyttats till den. De händelserna heter IN_CREATE och IN_MOVED_TO. Filen ser så här långt alltså ut såhär:</p>
<p><code>/var/www/uploads/ IN_CREATE,IN_MOVED_TO</code></p>
<p>Så långt har vi alltså angett vilken katalog som ska bevakas och vilka händelser vi ska bevaka. Återstår gör att ange vad vi vill göra när dessa händelser inträffar, alltså vilket kommando vi vill köra. Vi skulle också behöva veta vilken fil det är som flyttats till vår katalog för att kunna optimera just den. Lyckligtvis har incron två inbyggda variablar som gör det enklare för oss:</p>
<p><code>$@ den bevakade katalogen<br />
$# filen som triggat händelsen</code></p>
<p>Fler inbyggda variabler kan du läsa om i manualen, men i vårt fall är det just dessa två vi behöver. För att köra kommandot &#8221;optipng -o7&#8243; på varje png-fil som laddas upp hade vi alltså kunnat skriva:</p>
<p><code>/var/www/uploads/ IN_CREATE,IN_MOVED_TO /usr/bin/optipng -o7 $@$#</code></p>
<p>Våra variabler $@ och $# kommer här expandera till /var/www/uploads/uppladdadebilden.png</p>
<h2>Bedöma filtyp efter filändelse</h2>
<p>Detta funkar ju utmärkt så länge det är en PNG-fil vi laddat upp. Är det en JPEG-bild eller något annat format kommer <strong>optipng</strong> att säga ifrån. Vi behöver därför något sätt att särskilja de filer vi laddar upp efter filändelse eller typ. Finns även här olika sätt att lösa det på. Min lösning var ett kort shell-skript:</p>
<pre>#!/bin/bash
# Simple script to determine file type and pass file to appropriate
# program. To be called from incrontab.
# Written by Anders Eknert, anders@lonewolfmedia.se

if [ "$1" == "" ]; then

	echo "Usage: optimize [file].[jpg|jpeg|png]"

else
	# Set filename to first argument
	filename=$1
	# Set myindex to position of .
	myindex=`expr index $1 .`
	# Set extension to substring after .
	extension=${filename:myindex}
	# Check for filetype and process accordingly
	if [ "$extension" == "png" ]; then
		optipng -o7 $filename &amp;&gt; /dev/null

	elif [ "$extension" == "jpg" ]; then
		jpegoptim --strip-all $filename &amp;&gt; /dev/null

	elif [ "$extension" == "jpeg" ]; then
		jpegoptim --strip-all $filename &amp;&gt; /dev/null

	fi
fi</pre>
<p>Skriptet ovan (som jag döpt till optimize och gjort körbart med chmod +x) tar en parameter, nämligen ett filnamn och kontrollerar sedan filändelsen. Är den .png kommer den anropa<strong> optipng</strong> för att optimera bilden. Är den en bild av jpeg-typ kommer den anropa <strong>jpegoptim</strong> för samma uppdrag. Det kan tyckas vanskligt att bedöma en fil endast efter filändelse, men i mitt fall vet jag att det bara är jag som kommer att ladda upp bilder och kan därför förutsätta att jag inte laddar upp annat än bilder i korrekta format och filändelser.</p>
<h2>Slutligen (äntligen!)</h2>
<p>Skriptet placerar vi sedan i valfri katalog. Jag valde /home/anders/bin. Återstår då bara att ändra vår incrontab, vilket vi återigen gör med &#8221;incrontab -e&#8221;:</p>
<p><code>/var/www/uploads/ IN_CREATE,IN_MOVED_TO /home/anders/bin/optimize $@$#</code></p>
<p>Sådär! Varje gång någonting händer, specifikt när en ny fil skapas eller flyttas in  i vår uploads-katalog kommer <strong>incron</strong> att kalla på skriptet optimize som bedömer filtypen och sedan komprimerar den uppladdade bilden åt oss. Och vi kan nu framöver jobba mindre med optimering och mer åt att skapa innehåll!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/07/22/optimera-bilder-for-webben-i-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rekursiva funktioner i PHP</title>
		<link>http://www.lonewolfmedia.se/2011/07/20/rekursiva-funktioner-i-php/</link>
		<comments>http://www.lonewolfmedia.se/2011/07/20/rekursiva-funktioner-i-php/#comments</comments>
		<pubDate>Wed, 20 Jul 2011 19:13:48 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programmering]]></category>
		<category><![CDATA[katalogträd]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programmering]]></category>
		<category><![CDATA[rekursion]]></category>
		<category><![CDATA[rekursiv funktion]]></category>
		<category><![CDATA[rekursiva funktioner]]></category>
		<category><![CDATA[traversera]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=313</guid>
		<description><![CDATA[Vad är en rekursiv funktion? Funktioner är grundläggande inom all programmering. Rekursiva funktioner är kortfattat funktioner som anropar sig själva. Två kriterier ställs alltid på en rekursiv funktion: Den måste innehålla ett avslutande villkor. Med det innebär att det måste finnas ett tillstånd då funktionen slutar anropa sig själv. Gör den inte det kommer funktionen [...]]]></description>
			<content:encoded><![CDATA[<h2>Vad är en rekursiv funktion?</h2>
<p>Funktioner är grundläggande inom all programmering. Rekursiva funktioner är kortfattat funktioner som anropar sig själva. Två kriterier ställs alltid på en rekursiv funktion:</p>
<ol>
<li>Den måste innehålla ett avslutande villkor. Med det innebär att det måste finnas ett tillstånd då funktionen <em>slutar </em>anropa sig själv. Gör den inte det kommer funktionen anropa sig själv i oändlig tid (en. infinite loop), eller till du på annat sätt avbryter processen.</li>
<li>Ett rekursivt funktionsanrop ska alltid skilja sig från det tidigare anropet. Undvik <a title="Redundans" href="http://sv.wikipedia.org/wiki/Redundans">redundans</a>, det vill säga att behandla samma information flera gånger.</li>
</ol>
<h2>Exempel: En enkel rekursiv funktion i PHP</h2>
<p>En enkel rekursiv funktion skulle t.ex. kunna vara att räkna alla tal mellan (och inklusive) två angivna heltal. I PHP hade det sett ut så här:</p>
<pre>function recursive_count($start, $end)
{
	if ($start &lt;= $end)
	{
		echo $start.' ';
		$start++;
		recursive_count($start, $end);
	}
}

recursive_count(1,10);
echo "&lt;br /&gt;";
recursive_count(22, 30);</pre>
<p>Koden uppfyller båda kraven för en rekursiv funktion. Dels har den ett avslutande villkor (start-variabeln måste vara av lägre värde eller lika med end-variabeln, annars slutar funktionen) och då variabeln start ökar för varje iteration kommer heller aldrig samma funktionsanrop att göras. Koden ovan genererar förstås följande resultat:</p>
<pre>1 2 3 4 5 6 7 8 9 10
22 23 24 25 26 27 28 29 30</pre>
<h2>Varför använda rekursiva funktioner?</h2>
<p>Inga konstigheter så långt, eller hur? Men är det inte enklare att använda en vanlig loop? Jo, förmodligen! Och i de allra flesta fall (som i det ovan) är det svårt att motivera en rekursiv funktion framför användandet av en loop. Resultatet är detsamma, men för de allra flesta är det lättare att läsa och begripa vanliga loopar, kanske just för att de är mer vanligt förekommande.</p>
<p>I några fall är användandet av rekursiva funktioner mer naturliga än användandet av en loop. Ett exempel är t.ex. vid beräkning av <a title="Matematisk Fakultet" href="http://sv.wikipedia.org/wiki/Fakultet_(matematik)">matematisk fakultet</a>. Ett annat exempel där rekursiva funktioner brukar användas är då man vill söka igenom katalogstrukturer eller andra <a title="Datastruktur Träd" href="http://sv.wikipedia.org/wiki/Tr%C3%A4d_(datastruktur)">trädstrukturer</a>.</p>
<h2>Exempel: En rekursiv sökning i en katalogstruktur</h2>
<p>En lite mer komplex rekursiv funktion i PHP. Här börjar vi i en katalog och söker igenom varje underkatalog, deras underkataloger, osv, till hela katalogträdet är genomsökt.</p>
<pre style="overflow: auto;">function traverse_dir($dir)
{
	if (is_dir($dir))
	{
		$subdirs = get_subdirs($dir);

		foreach($subdirs as $subdir)
		{
			$cwd = $dir . '/' . $subdir;
			traverse_dir($cwd);
			echo $cwd."\n";
		}
	}
	else echo 'No such directory: ' . $dir;
}

function get_subdirs($dir)
{
	$dirs 	= array();
	$files	= @scandir($dir);	// ignore permission denied warnings

	if($files)			// if directory and permission not denied
	{
		foreach ($files as $file)
		{			// ignore . and ..
			if ((is_dir($dir.'/'.$file)) &amp;&amp; ($file != '.') &amp;&amp; ($file != '..'))
			{
				$dirs[] = $file;
			}
		}
	}
	return $dirs;
}

traverse_dir('/var/www');</pre>
<p>Funktionen traverse_dir tar här en katalog (&#8216;/var/www&#8217;) som enda parameter och söker sedan igenom den efter  underkataloger. Funktionen gör sedan ett anrop på sig självt och upprepar proceduren i varje underkatalog. Villkoren för funktionen är att fortsätta så länge det finns tillgängliga underkataloger, och då varje funktionsanrop innehåller underkatalogens namn kommer ej heller samma funktionsanrop att upprepas. Funktionen get_subdirs är ej en nödvändighet utan hade kunnat skrivas in i funktionen traverse_dir. Att tydligt separera rekursiva element och icke-rekursiva gör dock koden lättare att överblicka, förstå och felsöka.</p>
<h2>Slutligen</h2>
<p>Rekursiva funktioner används främst inom <a title="Funktionell programmering" href="http://sv.wikipedia.org/wiki/Funktionell_programmering">funktionell programmering</a>, och sällan i språk som PHP.  I många av de fall där rekursiva funktioner faktiskt hade varit användbara (som i fallet ovan) finns oftast färdiga funktioner att nyttja som utför samma sak men med betydligt färre rader kod (se exempelvis funktionen <a title="glob" href="http://php.net/manual/en/function.glob.php">glob</a> i PHP). Att ha koll på vad en rekursiv funktion är och hur den tillämpas kan ändå vara av värde, dels för att förstå hur de &#8221;färdiga&#8221; funktionerna arbetar, men också för att det är ytterligare ett verktyg som kan komma till nytta i andra programmeringssituationer.  Även om exemplen ovan är skrivna i PHP är principen förstås densamma oavsett programmeringsspråk.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/07/20/rekursiva-funktioner-i-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Använda history i bash</title>
		<link>http://www.lonewolfmedia.se/2011/07/17/anvanda-history-i-bash/</link>
		<comments>http://www.lonewolfmedia.se/2011/07/17/anvanda-history-i-bash/#comments</comments>
		<pubDate>Sun, 17 Jul 2011 00:43:38 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Systemadministration]]></category>
		<category><![CDATA[.bashrc]]></category>
		<category><![CDATA[.bash_history]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[BSD]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[grep]]></category>
		<category><![CDATA[histcontrol]]></category>
		<category><![CDATA[histfile]]></category>
		<category><![CDATA[histignore]]></category>
		<category><![CDATA[history]]></category>
		<category><![CDATA[histsize]]></category>
		<category><![CDATA[less]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[redhat]]></category>
		<category><![CDATA[sök]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=276</guid>
		<description><![CDATA[Introduktion till kommandot history I förra bloggposten tittade vi på hur man enkelt repeterar ett tidigare kommando med dubbla utropstecken (!!). Vad bash gör när det upptäcker de dubbla utropstecknen är att det kollar i historiken över tidigare använda kommandon och skriver sedan ut (expanderar) våra utropstecknen till det senaste av dem. Om det inte [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduktion till kommandot history</h2>
<p>I förra bloggposten tittade vi på hur man enkelt repeterar ett tidigare kommando med dubbla utropstecken (!!). Vad bash gör när det upptäcker de dubbla utropstecknen är att det kollar i historiken över tidigare använda kommandon och skriver sedan ut (expanderar) våra utropstecknen till det senaste av dem. Om det inte är det senaste vi vill använda då? Kommandot history i bash ger oss goda möjligheter att överblicka och använda historik, något jag tänkte gå in på närmare här.</p>
<p>Den enklaste introduktionen till <strong>history</strong> är något de allra flesta som jobbat i terminalen förmodligen känner till: tangentbordsknapparna <strong>pil upp</strong> och <strong>pil ner</strong> bläddrar upp/ner bland tidigare skrivna kommandon och skriver ut dem i prompten. Det är ett snabbt och smidigt sätt att komma tillbaks till något man precis skrivit men som kanske innehöll ett stavfel och därför inte gjorde det vi ville. Vill vi däremot gå långt tillbaks blir det snabbt tröttsamt att bläddra rad för rad. För att se en komplett lista över vad som tidigare skrivits in använder vi kommandot <strong>history</strong>:</p>
<pre>[anders@anders-laptop ~]$ history
1  cd /
2  ls
3  sudo apt-get update &amp;&amp; sudo apt-get upgrade
4  clear
5  history
...</pre>
<p>Som synes ovan får vi en komplett lista över alla tidigare kommandon. I exemplet här har det bara skrivits fem kommandon totalt sedan vårt operativsystem installerades (eller <strong>history-filen</strong> rensades, mer om den strax), något som förstås är osannolikt i verkligheten men bra för att visa upp. Förmodligen är listan så  lång att den täcker mer än hela skärmen. Skriv</p>
<pre>history | less</pre>
<p>för att skicka listan till kommandot <strong>less</strong> som gör det enkelt att bläddra upp och ner bland kommandohistoriken med antingen piltangenterna eller med page up/page down. Ett annat och förmodligen bättre alternativ är att skriva</p>
<pre>history &gt; historik.txt</pre>
<p>för att istället för att fylla upp skärmen skicka listan till en ny fil som vi i vårt fall pedagogiskt döper till historik.txt. Filen sparas i den nuvarande katalogen och kan sedan ögnas igenom i lugn och ro med valfri textredigerare. Slutligen kan vi också begränsa mängden data genom att säga till <strong>history</strong>-kommandot hur många av de senaste posterna vi vill visa:</p>
<pre>history 10</pre>
<p>returnerar alltså de 10 sista kommandona i vår historik. Notera att varje rad innehåller ett nummer framför namnet på kommandot som utförts. Detta indikerar förstås i vilken ordning kommandona skrivits in i historiken. Vi kan nu enkelt repetera valfritt kommando från <strong>history</strong>-listan genom att skriva ett enkelt utropstecken följt av det nummer i historiken vi vill repetera! I exemplet nedan repeterar vi det tredje kommandot i listan</p>
<pre>[anders@anders-laptop ~]$ !3</pre>
<p>Två enkla tecken ersätter alltså de <em>51 tecken</em> vi annars behövt för att uppdatera vårt operativsystem! Normalt sätt är det dock bättre att använda bashkommandot <strong>alias</strong> om man önskar ge kortare namn åt ofta repeterade långa kommandon.</p>
<h2>En djupare inblick i history</h2>
<p>Hur fungerar då history-kommandot? Jo, varje gång du trycker på Enter i terminalen sparas informationen du skrivit i prompten till minnet. När du senare stänger ner din terminal sparas historiken från minnet till din <strong>history</strong>-fil. Den läses sedan in nästa gång du startar en terminal så att du alltid har tillgång till tidigare historik. Vad heter då history-filen och var hittar vi den? Det är lite olika beroende på vilken distribution, men normalt sett ligger den i din hemkatalog och heter enkelt nog <strong>.bash_history</strong>. Du kan själv ta reda på var din historik finns sparad genom att skriva ut variabeln <strong>HISTFILE</strong></p>
<pre>[anders@anders-laptop ~]$ echo $HISTFILE
/home/anders/.bash_history</pre>
<p>Då den senaste historiken oftast ligger direkt i minne och endast skrivs till fil vid avslut är det dock sällsynt att man läser <strong>history</strong>-filen direkt. Det är det vi har kommandot <strong>history</strong> till! Viktigare är då variabeln <strong>HISTSIZE</strong> som anger hur många kommandon som ska sparas i din historik. Normalt brukar den ha ett värde mellan 500-1000. Det finns dock ingen anledning att snåla på det, så vi höjer värdet en aning med en extra nolla:</p>
<pre>[anders@anders-laptop ~]$ export HISTSIZE=10000</pre>
<p>För att säkerställa att detta värde laddas även vid omstart sparar vi ovanstående i vår <strong>.bashrc</strong>-fil i hemkatalogen. Denna fil laddas alltid in när du loggar in och är ett bra ställe att placera variabler du alltid vill ha tillgång till. Öppna den med din föredragna texteditor och skriv in samma som ovan där, alternativt:</p>
<pre>[anders@anders-laptop ~]$ echo "export HISTSIZE=10000" &gt;&gt; .bashrc</pre>
<p>Viktigt i ovanstående är att säkerställa dubbla &#8221;&gt;&#8221;-tecken (har de ett svenskt namn?)! Används bara ett kommer nämligen den befintliga <strong>.bashrc</strong>-filen skrivas över!</p>
<h2>Att söka i historiken</h2>
<p>Minns ni hur vi skickade data från <strong>history</strong> till programmet <strong>less</strong> för att enklare kunna bläddra i den? Det enklaste sättet att söka i din history är genom att istället skicka all data till programmet <strong>grep</strong>. Grep är ett otroligt mångfacetterat program, men kortfattat så söker det i sitt igenom en text och returnerar alla rader som innehåller den text vi söker efter. Testar vi t.ex. att söka efter alla kommandon innehållandes kommandot <strong>yum </strong>(Fedoras pakethanterare) ser vi följande:</p>
<pre>[anders@anders-laptop ~]$ history | grep "yum"
458  sudo yum install php-xml
460  sudo yum update
482  yum install fping
483  sudo yum install fping
539  sudo yum install preload
587  sudo yum update
...</pre>
<p>Användbart om du t.ex. undrar vad det egentligen var du installerade den där gången du kom hem från krogen!  Citationstecknen är inte nödvändiga så länge vi bara söker ett enkelt ord men behövs så fort vi letar efter ett kommando med fler ord eller parametrar, så som <strong>yum install</strong>. Det är därför god praxis att alltid citera texten du söker.</p>
<p>Ett annat alternativ för att söka igenom historiken efter ett specifikt kommando är att i terminalen trycka <strong>Ctrl+r</strong>. Du får då upp en prompt med texten <strong>(reverse-i-search)`&#8217; </strong>och kan sedan skriva in texten du söker. Tryck <strong>Ctrl+r</strong> upprepade gånger för att gå längre bak i historiken. När du hittat kommandot du letade efter trycker du vänster- eller högerpil för att flytta ut texten till prompten.</p>
<h2>Avancerad användning av history</h2>
<p>Två andra användbara variabler som läses av av <strong>history</strong>-kommandot är <strong>HISTIGNORE</strong> och <strong>HISTCONTROL</strong>. Det första är tämligen självförklarande; det anger nämligen precis vilka kommandon (om några) vi inte vill lagra i vår historik. Variabeln kan ta flera värden som separeras med ett kolon ( : ) och fungerar enligt följande syntax:</p>
<pre>HISTIGNORE="history:pwd"</pre>
<p>Ovanstående skulle göra att kommandona <strong>history</strong> och <strong>pwd</strong> upphörde registreras i vår historik. Värt att notera är att ovanstående endast ignorerar exakta träffar! Kommandot <code>history 10</code> hade alltså även fortsättningsvis registrerats då det inte matchar enbart &#8221;history&#8221;. Vill vi att kommandot ska ignoreras totalt oavsett följande värden/parametrar lägger vi bara till ett <strong>*</strong> vid slutet:</p>
<pre>HISTIGNORE="history*:pwd"</pre>
<p>Kommandon som <strong>history</strong> kan möjligen platsa i <strong>HISTIGNORE</strong>, men min rekommendation är att vara försiktig med vad du lägger till. Det motverkar förstås syftet med history-funktionen att ignorera vad som sker! En kraftfullare och mer användbar variabel är då <strong>HISTCONTROL</strong>. <strong>HISTCONTROL</strong> anger både vad som ska sparas och hur det sparas. Variabeln kan ges totalt fyra olika värden av vilket ett är en sammanslagning av två andra. Värdena är som följer:</p>
<ul>
<li><strong>ignorespace</strong> &#8211; ignorera alla kommandon som börjar med ett mellanslag. Registrerar alltså &#8221;cd ..&#8221; men inte &#8221; cd ..&#8221;. Användbart om man då och då önskar undanta ett kommando från history.</li>
<li><strong>ignoredups</strong> &#8211; ignorera dubbletter i följd. Skriver du alltså exempelvis &#8221;ls&#8221; flera gånger i följd kommer endast den sista att registreras.</li>
<li><strong>ignoreboth</strong> &#8211; Sammanslagning av de två ovanstående parametrarna, aktiverar både <strong>ignorespace</strong> och <strong>ignoredups</strong>.</li>
<li><strong>erasedups</strong> &#8211; ignorera samtliga dubbletter i din historik! Skriver du exempelvis &#8221;ls&#8221; kommer samtliga förekomster av kommandot &#8221;ls&#8221; att tas bort från din historik och ersättas med enbart det sista. Användning av denna parameter känns svår att motivera annat än i specialfall.</li>
</ul>
<h2>Slutligen</h2>
<p>Har du orkat ända hit bör du nu ha en god överblick över <strong>history</strong>-kommandot och hur det används i praktiken. För att avsluta bjuder jag här på en gammal goding i bash-sammanhang, nämligen en salig blandning kommandon sammansatta med pipes i en enda lång one-liner. Resultatet; en tio-i-topp-lista över de mest använda kommandona i historiken, sorterade efter antal!</p>
<pre style="overflow: scroll;">[anders@anders-laptop ~]$ history | awk '{print$2}' | awk 'BEGIN {FS="|"}{print $1}' | sort | uniq -c | sort -n | tail | sort -nr</pre>
<p>Resultatet för mig blir:</p>
<pre>    157 git
    143 ls
    129 sudo
    101 cd
     42 echo
     34 man
     33 su
     28 mysql
     24 chmod
     23 rm</pre>
<p>Vad blir det för dig? Klipp gärna in i kommentarerna!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/07/17/anvanda-history-i-bash/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bash: Upprepa kommando med dubbla utropstecken</title>
		<link>http://www.lonewolfmedia.se/2011/07/16/bash-upprepa-kommando-med-dubbla-utropstecken/</link>
		<comments>http://www.lonewolfmedia.se/2011/07/16/bash-upprepa-kommando-med-dubbla-utropstecken/#comments</comments>
		<pubDate>Sat, 16 Jul 2011 19:12:06 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Systemadministration]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[dubbla utropstecken]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[history]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[root]]></category>
		<category><![CDATA[sudo]]></category>
		<category><![CDATA[systemadministration]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=253</guid>
		<description><![CDATA[Glömde du sudo? Alla som använt Ubuntu eller någon annan linuxdistribution där sudo används för att utföra ett kommando som kräver root-rättigheter har säkerligen någon gång glömt att skriva just sudo innan det kommando man vill utföra. Eller hur? Det ger vanligtvis till svars: [anders@anders-laptop ~]$ cat /etc/shadow cat: /etc/shadow: Åtkomst nekas Detta förstås för [...]]]></description>
			<content:encoded><![CDATA[<h2>Glömde du sudo?</h2>
<p><a href="http://www.lonewolfmedia.se/wp-content/uploads/2011/07/exmarksthespot.png"><img class="size-full wp-image-266 alignright" title="Dubbla utropstecken i bash" src="http://www.lonewolfmedia.se/wp-content/uploads/2011/07/exmarksthespot.png" alt="Dubbla utropstecken i bash" width="80" height="80" style="float: right; margin: 0 0 10px 10px;" /></a></p>
<p>Alla som använt Ubuntu eller någon annan linuxdistribution där <strong>sudo</strong> används för att utföra ett kommando som kräver root-rättigheter har säkerligen någon gång glömt att skriva just <strong>sudo</strong> innan det kommando man vill utföra. Eller hur? Det ger vanligtvis till svars:</p>
<pre>[anders@anders-laptop ~]$ cat /etc/shadow
cat: /etc/shadow: Åtkomst nekas</pre>
<p>Detta förstås för att vi glömde <strong>sudo</strong> och därmed inte har rättigheter att läsa /etc/shadow-filen. Jag glömmer det ofta i kombination med <strong>apt-get install</strong> då jag behöver hämta hem nya paket och program. Vad göra?</p>
<h2>Lugn, det ordnar sig</h2>
<p>Vi kan förstås alltid skriva om kommandot med prefixet sudo.</p>
<pre>[anders@anders-laptop ~]$ sudo cat /etc/shadow
nobody:*:15014:0:99999:7:::
usbmuxd:!!:15072::::::
avahi-autoipd:!!:15072::::::
...</pre>
<p>Har vi just skrivit ett långt kommando (så som i det tidigare <a title="Enkel backup med rsync lokalt och över SSH" href="http://www.lonewolfmedia.se/2011/07/01/enkel-backup-med-rsync-lokalt-och-over-ssh/">rsync-exemplet</a>) med flera parametrar ter sig dock detta jobbigt, och jobbiga saker vill vi ju alltid undvika! Hur görs det mindre jobbigt? Vi kan förstås  trycka <strong>pil upp</strong> för att bläddra upp ett steg i kommandohistoriken, trycka på <strong>home</strong>-knappen för att komma till början av raden och skriva <strong>sudo</strong> där. Nu börjar det bli riktigt enkelt! Det enklaste alternativet kvarstår dock, nämligen användandet av <strong>dubbla utropstecken</strong>:</p>
<pre>[anders@anders-laptop ~]$ sudo !!</pre>
<p>De dubbla utropstecknen är en inbyggd funktion i <strong>bash</strong> som alltid returnerar det senast inslagna kommandot. Att skriva ovanstående blir alltså i vårt fall samma sak som att skriva:</p>
<pre>[anders@anders-laptop ~]$ sudo cat /etc/shadow</pre>
<p>Enkelt, eller hur?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/07/16/bash-upprepa-kommando-med-dubbla-utropstecken/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Scanna lokalt nätverk efter ip-adresser med ping, fping och nmap</title>
		<link>http://www.lonewolfmedia.se/2011/07/04/scanna-lokalt-natverk-efter-ip-adresser-med-ping-fping-och-nmap/</link>
		<comments>http://www.lonewolfmedia.se/2011/07/04/scanna-lokalt-natverk-efter-ip-adresser-med-ping-fping-och-nmap/#comments</comments>
		<pubDate>Mon, 04 Jul 2011 16:02:16 +0000</pubDate>
		<dc:creator>Anders</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Nätverk]]></category>
		<category><![CDATA[Systemadministration]]></category>
		<category><![CDATA[broadcastadress]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[fedora]]></category>
		<category><![CDATA[fping]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nmap]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[ping]]></category>
		<category><![CDATA[pingsvep]]></category>
		<category><![CDATA[redhat]]></category>
		<category><![CDATA[systemadministration]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.lonewolfmedia.se/?p=222</guid>
		<description><![CDATA[Pingsvep Det kan ofta vara av nytta att få reda på vilka andra datorer som befinner sig på samma nätverk. En enkel och snabb metod att göra det är via ett så kallat pingsvep. Nedan följer tre olika metoder. I exemplen nedan använder vi nätverket 192.168.0.xxx vilket är vanligast för hemnätverk. Byt förstås ut efter [...]]]></description>
			<content:encoded><![CDATA[<h2>Pingsvep</h2>
<p>Det kan ofta vara av nytta att få reda på vilka andra datorer som befinner sig på samma nätverk. En enkel och snabb metod att göra det är via ett så kallat <a title="Pingsvep" href="http://en.wikipedia.org/wiki/Ping_sweep">pingsvep</a>.</p>
<p>Nedan följer tre olika metoder. I exemplen nedan använder vi nätverket 192.168.0.xxx vilket är vanligast för hemnätverk. Byt förstås ut efter behov!</p>
<p><strong>[ Observera att det kan anses vara en fientlig handling att göra ett pingsvep på nätverk som du inte själv administrerar. Trots att metoden i sig är helt ofarlig är den ofta ett första steg en illvillig användare skulle ta för att upptäcka möjliga mål på nätverket. Använd därför endast på de nätverk du själv äger och har kontroll över, så som ditt hemnätverk. ]</strong></p>
<h2>Metod 1 &#8211; ping</h2>
<p>Den första och enklaste metoden är att använda ping för att pinga nätverkets <a title="Broadcast adress" href="http://en.wikipedia.org/wiki/Broadcast_address">broadcastadress</a>:</p>
<p><code class="postcode">ping -b 192.168.0.255</code></p>
<p>Ovanstående skickar en ping till nätverkets broadcastadress och listar sedan svaren som kommer tillbaks. Responsen kan se ut ungefär såhär:<br />
<p>
								<pre class="Plum_Code_Box"><code class="">WARNING: pinging broadcast address
PING 192.168.0.255 (192.168.0.255) 56(84) bytes of data.
64 bytes from 192.168.0.193: icmp_req=1 ttl=64 time=4.28 ms
64 bytes from 192.168.0.199: icmp_req=1 ttl=64 time=4.92 ms (DUP!)
64 bytes from 192.168.0.8: icmp_req=1 ttl=64 time=5.40 ms (DUP!)
64 bytes from 192.168.0.8: icmp_req=2 ttl=64 time=2.06 ms</code>
									</pre>
							</p></p>
<p>Vi får alltså klart för oss att datorerna med ip-adresserna 192.168.0.8, 192.168.0.193 och 192.168.0.199 alla är online och svarar på vårt anrop. En fördel med ping är att det är installerat som standard i nästan alla UNIX-maskiner. Nackdelen är dock att långt ifrån alla datorer svarar på anrop till broadcastadressen. Vi skulle därför kunna loopa (repetera) vanliga ping-förfrågningar till alla möjliga adresser, men det blir snabbt onödigt krånligt. Låt oss därför titta på nästa metod &#8211; <strong>fping</strong>.</p>
<h2>Metod 2 &#8211; fping</h2>
<p>En bättre metod är att använda <strong>fping</strong> som är gjort just för detta ändamål. <strong>fping</strong> finns normalt inte installerat som standard men finns tillgängligt i de flesta distributioners pakethanterare. En enkel <strong>yum install fping</strong> eller <strong>apt-get install fping</strong> och programmet är färdigt att användas.</p>
<p><code class="postcode">fping -ga 192.168.0.0/24 2&gt;/dev/null</code></p>
<p>Ger följande resultat:<br />
<p>
								<pre class="Plum_Code_Box"><code class="">192.168.0.2
192.168.0.8
192.168.0.20
192.168.0.193
192.168.0.198
192.168.0.199
192.168.0.1</code>
									</pre>
							</p></p>
<p>Notera förstås att vi får en betydligt bättre respons här än när vi pingade broadcastadressen! Växeln <code class="postcode">-a</code> anger att vi vill se datorer som är online (alive) på nätverket. Växeln <code class="postcode">-g</code> anger att vi ska pinga en lista angiven antingen efter nätmask (i vårt fall /24) eller efter startadress och slutadress. Exemplet kan alltså lika gärna skrivas så här:</p>
<p><code class="postcode">fping -ga 192.168.0.0 192.168.0.255 2&gt;/dev/null</code></p>
<p>Det sista <code class="postcode">2&gt;/dev/null</code> anger att terminalen ska skicka felmeddelanden till /dev/null istället för till teminalprompten. Det gör vi för att slippa meddelanden av typ &#8221;host unreachable&#8221; över hela skärmen, men vill man se alla meddelanden är det förstås bara att strunta i det sista stycket.</p>
<h2>Metod 3 &#8211; nmap</h2>
<p><strong>nmap</strong> är ett multiverktyg för nätverksadministration och innehåller en hel uppsjö funktioner. Vanligaste användningsområdet är förmodligen att scanna efter öppna portar på en specifik adress. Det går dock alldeles utmärkt att scanna efter tillgängliga datorer också. Finns <strong>nmap</strong> inte förinstallerat i din distribution hittar du det i pakethanteraren. <strong>nmap</strong> finns även för Mac OS X och Microsoft Windows och laddas hem på <a title="nmap download" href="http://nmap.org/download.html">nmaps hemsida</a>. För att söka igenom det lokala nätverket med <strong>nmap</strong> skriver vi:</p>
<p><code class="postcode">nmap -sn 192.168.0.0/24</code></p>
<p>Vilket ger oss något i stil med nedanstående till svar:<br />
<p>
								<pre class="Plum_Code_Box"><code class="">Starting Nmap 5.50 ( http://nmap.org ) at 2011-07-04 17:47 CEST
Nmap scan report for 192.168.0.1
Host is up (0.00091s latency).
Nmap scan report for 192.168.0.2
Host is up (0.00068s latency).
Nmap scan report for qnap.localdomain (192.168.0.8)
Host is up (0.016s latency).
Nmap scan report for b3.localdomain (192.168.0.20)
Host is up (0.0056s latency).
Nmap scan report for 192.168.0.193
Host is up (0.0027s latency).
Nmap scan report for 192.168.0.198
Host is up (0.048s latency).
Nmap scan report for 192.168.0.199
Host is up (0.047s latency).
Nmap done: 256 IP addresses (7 hosts up) scanned in 2.55 seconds</code>
									</pre>
							</p></p>
<p>Växeln <code class="postcode">-sn</code> anger att vi inte vill skanna portar utan endast leta efter andra datorer. Som synes  skriver <strong>nmap</strong> ut både ip-nummer och svarstid. Programmet tar dessutom en titt i <code class="postcode">/etc/hosts</code> för att se om några av de datorer som upptäcks har ett hostname angivit där.</p>
<h2>Slutligen</h2>
<p>Att ta reda på vilka datorer som finns online på nätverket är förstås användbart i många sammanhang. Ovanstående är inte tänkt som en djupare ingång i varken <strong>ping</strong>, <strong>fping</strong> eller <strong>nmap, </strong>men en snabb introduktion till hur programmen kan användas till just det. Frågor eller synpunkter? Lämna gärna en kommentar!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonewolfmedia.se/2011/07/04/scanna-lokalt-natverk-efter-ip-adresser-med-ping-fping-och-nmap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

