SSH-login med Google Authenticator

tva-1024x576

Anslut med ssh – få en kod i din smartphone – skriv in koden – logga in! Hur coolt som helst!
Läs mer i min artikel på ExploreCurate om hur du konfigurerar hela kalaset.

0 kommentarer.

Prompt i terminalen som visar git- och svn-status

Här kommer ett tips om du arbetar med Git eller SVN ifrån terminalen. Det går att modifiera prompten så att den visar statusen för aktuell arbetskopia.

Normalt ser prompten ut ungefär så här, beroende på distribution (jag kör Linux Mint för tillfället).

Min prompt

När jag hoppar in i en katalog som är utcheckad från SVN ser det ut så här.

Nu syns information om aktuell branch och revision, i detta fall är branchen branches/RB-1.8 och revisionen 837. Att det visas i grönt betyder att det inte finns några modifieringar. Om jag ändrar i en fil kommer prompten att bli röd.

Modifierad arbetskopia

Arbetar du med Git syns liknande information i prompten. På bilden nedan syns hur jag går in i en katalog som är klonad från Git, skapar en ny branch med git flow och redigerar en fil. Prompten byter även här färg till rött när det finns modifierade filer och när jag committar mina ändringar ändrar färgen till grön igen. Jag slutför min feature (branch) och promten ändras igen så att aktuell branch (develop) visas.

Git prompt

För att få den här funktionaliteten läggar man till kodsnutten nedan i filen .bashrc som finns i din hemkatalog, finns den inte går det bra att skapa den. För att scriptet ska fungera måste filen /etc/bash_completion.d/git finnas, den kommer vanligen med i installationen av git, åtminstone om du installerar med apt-get install git.

Här kommer då koden.

# Custom PS1 prompt to show git and svn repos, branches and their status
Color_Off="\[\033[0m\]"       # Text Reset
Green="\[\033[0;32m\]"        # Green
BGreen="\[\033[1;32m\]"       # Green
BYellow="\[\033[1;33m\]"      # Yellow
IRed="\[\033[0;91m\]"         # Red
PathShort="\w"

export SVN_SHOWDIRTYSTATE=1
export PS1='$(git branch &>/dev/null;\
if [ $? -eq 0 ]; then \
  # In Git repo
  echo "$(echo `git status` | grep "nothing to commit" > /dev/null 2>&1; \
  if [ "$?" -eq "0" ]; then \
    # Clean repository - nothing to commit
    echo "'$Green'"$(__git_ps1 " (%s)"); \
  else \
    # Changes to working tree
    echo "'$IRed'"$(__git_ps1 " {%s}"); \
  fi) '$BYellow$PathShort$Color_Off'\$ "; \
elif [[ -d ".svn" ]] ; then \
  # In SVN repo 
  r=`__svn_rev` ;\
  b=`__svn_branch` ;\
  out=`svn status | grep -c ".*"` ; \
  if [ $out -eq 0 ] ; then \
    echo "'$Green'[$b:$r] '$BYellow$PathShort$Color_Off'\$ "; \
  else \
    echo "'$IRed'[$b:$r] '$BYellow$PathShort$Color_Off'\$ "; \
  fi; 
else \
  @2 - Prompt when not in GIT repo
  echo " '$BGreen'\u@\h '$BYellow$PathShort$Color_Off'\$ "; \
fi)'

# Outputs the current trunk, branch, or tag
__svn_branch() {
    local url=
    if [[ -d .svn ]]; then
        url=`svn info | awk '/URL:/ {print $2}'`
        root=`svn info|awk '/Repository Root/ {print $3}'`
        if [[ $url =~ trunk ]]; then
            echo trunk
        elif [[ $url =~ /branches/ ]]; then
            echo ${url##$root/}
        elif [[ $url =~ /tags/ ]]; then
            echo ${url##$root/}
        fi
    fi
}

# Outputs the current revision
__svn_rev() {
    local r=$(svn info | awk '/Revision:/ {print $2}')
    if [ ! -z $SVN_SHOWDIRTYSTATE ]; then
        local svnst flag
        svnst=$(svn status | grep '^\s*[?ACDMR?!]')
        [ -z "$svnst" ] && flag=*
        r=$r$flag
    fi
    echo $r
}

Rock on!

0 kommentarer.

Tömma cache och generera autoloads i eZ Publish ifrån Netbeans

För att slippa hoppa ut i terminalen och köra scripten när man uppdaterat från svn, kan man göra följande.

Skapa en fil, exempelvis run.php i roten på ez-installationen. Kom ihåg att lägga till den i svn ignore! Filen ska se ut så här:


<?php
/*
 * Rensa cache och generera autoloads
 *
 */
system("/usr/bin/php bin/php/ezpgenerateautoloads.php");
system("/usr/bin/php bin/php/ezcache.php --clear-all --purge");
?>

1. Öppna projektet i Netbeans.
2. Klicka på File-menyn och välj Project Properties.
3. Klicka på Run Configuration i vänster-menyn.

Gör följande inställningar:
Run As: Script (run in command line)
Index File: run.php (Alltså filen du skapade tidigare)
Working Directory: /var/www/hmpr (Alltså ez root)

Se bilden hur det ska se ut.

Netbeans inställningar

Klicka Ok.
Nu kan man köra detta genom att antingen välja Run-menyn och sedan Run Project, eller genom att trycka F6!

0 kommentarer.

Använd error-loggen!

error_logOfta när jag ska hjälpa någon av våra utvecklare med ett problem är min första fråga: Vad står det i loggen? Apache och php har väl utvecklade loggfunktioner och man kan med hjälp av dom få en ganska bra fingervisning om vad som orsakar problemet.  Exempelvis kan det stå:

[Fri Mar 02 17:38:08 2012] [error] [client 127.0.0.1] PHP Parse error:  syntax error,
unexpected ';' in /var/www/smhifb/application/controllers/start.php on line 64</pre>

Just det här felet beror förmodligen på att det saknas en slutparantes eller klammer på rad 64 i filen start.php (Nu var det här bara ett exempel, eftersom rena syntaxfel så klart hittas av din IDE, som jag utgår ifrån att  du använder.)

När jag utvecklar har jag alltid ett terminalfönster öppet som visar loggarna i realtid så att jag snabbt ska kunna se om det händer något som inte borde hända, när man surfar in i applikationen.  Även om man inte märker några fel när man surfar så händer det ändå att det dyker upp fel i loggen. Oftast är detta då varningar eller notiser, vilka inte är fatala för körningen av koden. Det är väldigt vanligt att man ändrar i php.ini så att notiser och till och med varningar inte visas i loggen, koden fungerar ju ändå. Gör inte det! Se till att varningar och notiser loggas och fixa till felen! Den enda anledningen till att folk slår av notiser och varningar är att dom antingen är lata eller programmerar dåligt.  Det är lika vanligt att de som har varningar och notiser aktiverat inte bryr sig om att rätta till dessa fel, eftersom det fungerar ändå. Var inte en lat programmerare! Konsekvensen blir att koden inte blir så optimerad som den kunnat vara, dessutom kan små fel bli betydligt större längre fram.

Ett litet tips, använd programmet multitail. Multitail är ett program som körs i konsollen och kan visa flera loggar samtidigt i realtid. Vanligen när man vill se en logg i realtid använder man sig av kommandot tail med växeln -f, exempelvis:

tail -f /var/log/httpd/error_log

Med multitail kör man istället

multitail /var/log/httpd/error_log /var/log/httpd/access_log

Detta medför att terminalfönstret delas på två och visar en logg i varje del. Det är otroligt smidigt att se error-loggen i den ena delen och access-loggen i den andra. Det allra bästa med multitail är att det har syntax highlighting, det skriver alltså ut olika saker i olika färger, vilket gör det enklare  att se i loggen. multitail
Så, en kort sammanfattning.

  • Använd error-loggen
  • Se till att varningar och notiser visas
  • Fixa felen, även varningar och notiser
  • Visa loggen i realtid i ett eget terninalfönster
  • Använd multitail

Kod ska vara kul  och är det också med rätt förutsättningar, en av dessa förutsättningar är att veta vad som är fel och framför allt veta att det är fel.

2 kommentarer.

wget i OS X Lion

wget för osxKommandot wget, som bland annat kan användas för hämta filer och sidor via http och ftp, finns tyvärr inte i Osx Lion. Det här är något som irriterat mig ett tag, men som jag av olika anledningar inte tagit tag i än. Så idag när jag satt och skrev lite nya alias för diverse kommandon (jag gör så för exempelvis de ssh-anslutningar jag ofta använder, det går fortare att bara skriva goserver1 istället för att skriva ssh -p 2211 daniel@server1.domain.com), så kom jag på att curl faktiskt finns i Lion. Varför helt enkelt inte göra ett alias för wget till curl? Så här gör man.

I min hemkatalog finns en fil som heter .bash_profile, i den lägger jag till följande rad:

alias wget='curl -O'

Sedan sparar jag filen och stänger alla eventuella terminal-fönster och öppnar ett nytt. Nu kan jag använda mig av kommandot wget för att hämta hem filer:

wget http://server1.domain.com/path/large_file.zip

Det här blir så klart inte exakt detsamma som att ha wget installerat på riktigt, eftersom wget kan göra så mycket mer än att bara hämta en fil, men i 99% av fallen är det just bara det jag använder det till. Ska jag göra något mer avancerat snickrar jag hellre ihop ett skript, antingen i bash eller i PHP.

OSX – som Linux fast snyggare!

1 kommentarer.

Manuell databasfråga i eZ Publish, för ökad prestanda

eZ Publish är ett mycket kompetent system för innehållshantering, men ibland kan man behöva gå förbi alla praktiska funktioner som finns. Bland annat kan det vara aktuellt att göra detta när man vill lista en stor mängd data i tabellform, till exempel en medlemslista. Vi hade ett projekt där kunden ville att ungefär 900 medlemmar skulle visas samtidigt i en lista, samt på en Googlekarta, vilket gjorde att det inte blev riktigt optimalt att använda de befintliga funktionerna i eZ Publish, det gick helt enkelt för långsamt. För att lösa problemet byggde jag en modul med en custom fetch som tog hand om det hela istället för de inbyggda fetch-funktionerna. Hur man bygger en egen modul finns väl dokumenterat och det är inget jag tänker beskriva nu, däremot fanns det väldigt lite information (i princip obefintlig) om hur man hämtar ut information direkt ur databasen. Genom att studera databasen och med hjälp av lite reverse enginering kom jag fram till följande.

Om man utgår från tabellen ezcontentobject_tree som representerar nodträdet så kan man köra en sql-fråga för att få fram alla barn till en viss nod.

SELECT et.contentobject_id id
FROM   ezcontentobject_tree et
WHERE  et.parent_node_id = 2

Satsen ovan ger följande resultat.

+------+
| id   |
+------+
|   58 |
|   59 |
|   76 |
|  122 |
+------+

Alltså, en lista på de objekt-id’n som finns direkt under noden med id 2.

Information om varje objekt lagras i tabellen ezcontentobject_attribute, därför gör man en JOIN för att få ut även denna information. Satsen blir då så här.

SELECT et.contentobject_id id,
       en.data_text        namn
FROM   ezcontentobject_tree et
       LEFT JOIN ezcontentobject_attribute en
         ON et.contentobject_id = en.contentobject_id
            AND et.contentobject_version = en.version
            AND en.contentclassattribute_id = 361
WHERE  et.parent_node_id = 97
       AND et.contentobject_is_published = 1
       AND et.is_hidden = 0
       AND et.is_invisible = 0

Här hämtas alltså information från tabellen ezcontentobject_attribute med contentclassattribut_id lika med 361, vilket är objektets namn i detta fall. Detta id hittar man i administrationsgränssnittet under Setup->Classes och sedan den klass objektet är en instans av. Se bilden nedan.

Jag har i satsen ovan lagt  till tre villkor i slutet som ser till att man bara får träffar på noder som är publicerade och synliga på sajten.

Resultatet blir.

+------+-----------------------------+
| id   | namn                        |
+------+-----------------------------+
|  398 | COOP OBS! LILLESTRØM        |
|  399 | COOP OBS! LØREN             |
|  400 | COOP OBS! MARIERO           |
|  401 | COOP OBS! MORENEN           |
|  402 | COOP OBS! NORD AVD. HARSTAD |
+------+-----------------------------+

För varje attribut man vill hämta ut måste man alltså göra en extra JOIN enligt ovan.

Om man vill hämta attribut av typen ezurl måste man göra två extra JOINs eftersom själva urlen sparas i tabellen ezurl och korskopplas i tabellen ezurl_object_link. Det man måste lägga till är alltså.

LEFT JOIN ezcontentobject_attribute eu
  ON et.contentobject_id = eu.contentobject_id
     AND et.contentobject_version = eu.version
     AND eu.contentclassattribute_id = 367
LEFT JOIN ezurl_object_link eol
  ON eu.id = eol.contentobject_attribute_id
     AND eu.version = eol.contentobject_attribute_version
LEFT JOIN ezurl eurl
  ON eol.url_id = eurl.id

Den kompletta sql-frågan blev så här.


SELECT et.contentobject_id id,
       en.data_text        name,
       etel.data_text      tele,
       efa.data_text       fax,
       pnr.data_text       postnr,
       por.data_text       postort,
       em.data_text        email,
       eurl.url            url
FROM   ezcontentobject_tree et
       LEFT JOIN ezcontentobject_attribute en
         ON et.contentobject_id = en.contentobject_id
            AND et.contentobject_version = en.version
            AND en.contentclassattribute_id = 361
       LEFT JOIN ezcontentobject_attribute etel
         ON et.contentobject_id = etel.contentobject_id
            AND et.contentobject_version = etel.version
            AND etel.contentclassattribute_id = 362
       LEFT JOIN ezcontentobject_attribute efa
         ON et.contentobject_id = efa.contentobject_id
            AND et.contentobject_version = efa.version
            AND efa.contentclassattribute_id = 363
       LEFT JOIN ezcontentobject_attribute pnr
         ON et.contentobject_id = pnr.contentobject_id
            AND et.contentobject_version = pnr.version
            AND pnr.contentclassattribute_id = 364
       LEFT JOIN ezcontentobject_attribute por
         ON et.contentobject_id = por.contentobject_id
            AND et.contentobject_version = por.version
            AND por.contentclassattribute_id = 365
       LEFT JOIN ezcontentobject_attribute em
         ON et.contentobject_id = em.contentobject_id
            AND et.contentobject_version = em.version
            AND em.contentclassattribute_id = 366
       LEFT JOIN ezcontentobject_attribute eu
         ON et.contentobject_id = eu.contentobject_id
            AND et.contentobject_version = eu.version
            AND eu.contentclassattribute_id = 367
       LEFT JOIN ezurl_object_link eol
         ON eu.id = eol.contentobject_attribute_id
            AND eu.version = eol.contentobject_attribute_version
       LEFT JOIN ezurl eurl
         ON eol.url_id = eurl.id
WHERE  et.parent_node_id = 97
       AND et.contentobject_is_published = 1
       AND et.is_hidden = 0
       AND et.is_invisible = 0

Resultatet av frågan blir.

+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+
| id   | name                        | tele        | fax         | postnr | postort    | email                        | url  |
+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+
|  398 | COOP OBS! LILLESTRØM        | 63 80 55 00 | 63 81 38 30 | 2000   | LILLESTRØM | xxxxx.xxxxx@obs.coop.no      | NULL |
|  399 | COOP OBS! LØREN             | 22 65 50 65 | 22 64 57 17 | 0513   | OSLO       | xxx.xxx.xxx.xxx@obs.coop.no  | NULL |
|  400 | COOP OBS! MARIERO           | 51 82 50 50 | 51 82 50 51 | 4095   | STAVANGER  | xxxx.xxxxxxx@obs.coop.no     | NULL |
|  401 | COOP OBS! MORENEN           | 69 84 65 00 | 69 84 65 51 | 1859   | SLITU      | xxxxxx.xxxxxxx@obs.coop.no   | NULL |
|  402 | COOP OBS! NORD AVD. HARSTAD | 77 02 89 00 | 77 02 89 01 | 9406   | HARSTAD    | xxxxxx.xxxxxx.x@nord.coop.no | NULL |
+------+-----------------------------+-------------+-------------+--------+------------+------------------------------+------+

Den här datan använde vi sedan för att bygga en lista över medlemmarna. Vi valde dessutom att generera html-koden direkt i modulen eftersom vi fortfarande inte var helt nöjda med prestandan när vi använde de befintliga template-funktionerna.

Resultatet kan du se här: http://elektronikkbransjen.no/Medlem/Medlemsoversikt

All utdata från sql-satserna ovan är förkortade, den vekliga utdatan var mer än 900 rader.
Epost-adresserna i utdatan ovan är modifierade på grund av sekretess.

0 kommentarer.

Din dagliga dos av ko

Kommandot apt-get, som används för att hantera paket i bland annat Ubuntu, har ett roligt påskägg inbyggt. Normalt använder man det exempelvis så här:

apt-get install lynx

Kommandot ovan laddar ner och installerar den textbaserade webbläsaren lynx. Om man däremot skriver:

apt-get moo

så visas en ascii-bild av en liten ko som säger ”Have you mooed today?” Det är såna här små saker som gör Linux så otroligt charmigt att arbeta med  :)

0 kommentarer.

Dynamisk VirtualHost i Apache

Utvecklar du sajter och lägger varje gång till en ny Virtual Host i Apaches konfigurationsfil så har jag ett tips, VirtualDocumentRoot! Om du har en utvecklingsdomän som heter domain.com skapar du ett wildcard i DNS’en ( *.domain.com ) som pekar mot din utevecklingsmaskin. I Apache’s konfiguration gör du sedan så här:


<VirtualHost *:80>
ServerAlias *.domain.com
UseCanonicalName Off
VirtualDocumentRoot /var/www/dev/%1
ErrorLog logs/dev-errorlog
CustomLog logs/dev-access.log combined
</VirtualHost>

Den här metoden kräver att modulen mod_vhost_alias är laddad i Apache.

Nu kan du skapa en katalog i /var/www/dev för varje nytt projekt och du kan automatiskt surfa till det genom att använda katalogens namn som subdomän. Alltså, /var/www/dev/projekt1 kan kommas åt via http://projekt1.domain.com.

Hur smidigt som helst :)

0 kommentarer.

Dropbox, manna från teknikhimlen

Dropbox måste vara teknikgudens gåva till… hmm… ja åtminstone mig. För den som inte vet vad Dropbox är så är det en tjänst (gratis) som gör att man får en katalog på datorn som synkroniseras med en server någonstans på det stora vida Internet. Jag installerar en liten programvara på min dator som ser till att nya filer, som jag sparar i katalogen, kopieras till servern. Det utomordentligt finurliga i det hela är att den sparar historik på alla filer, om jag vill kan jag alltså gå tillbaka till en fil som den såg ut för en vecka sedan. Och, det kanske viktigaste för mig, det fungera på alla OS jag använder. Windows, Mac OSX, Ubuntu Linux och Iphone iOS har alla klienter för Dropbox, vilket i mitt fall betyder att när jag sparat en fil på datorn på jobbet, så har jag den automatiskt i datorn hemma, i telefonen och i den bärbara. Skulle jag komma till en datorn som jag inte synkroniserar med Dropbox kan jag alltid logga in på deras webbsida, där jag också har access till mina filer.

Vill man dela med sig av en fil kan man kopiera den till katalogen Public, som finns i din Dropbox-katalog. Sedan är det bara att högerklicka på filen och välja ”Copy public link” och sedan klistra in länken i exempelvis ett mail. Personen som får mailet kan nu klicka på länken och ladda ner filen.

Dropbox är ett lysande exempel på hur Internet kan användas för att skapa nyttiga tjänster. Tjänster som snurrar någonstans i bakgrunden utan att man tänker på det, men som är så otroligt viktiga. Precis sånt som jag gillar :)

Om du inte har Dropbox tycker jag verkligen att du ska testa det. Även om du inte använder fler än en dator, är Dropbox en bra och automatisk säkerhetsbackup. Dropbox är som sagt gratis och då ingår 2GB datalagring. Behöver du mer utrymme än så kan man betala extra, 50GB för $9.99 i månaden eller $99.00 per år, samt 100GB för $19.99 per månad eller $199.00 per år.

0 kommentarer.

Versionshantering med Subversion

När man utvecklar så är det så klart själva kodandet man har i fokus, inget konstigt med det, men när man bygger större sajter eller webb-applikationer där man är fler än en utvecklare måste man börja tänka på andra saker.  Man måste bland annat på något vis dela upp arbetet så att flera personer inte gör samma sak, man måste även se till att två personer inte redigerar samma fil samtidigt för att sedan skriva över varandras ändringar. En lösning på dessa problem är att använda sig av ett versionshanteringssystem, exempelvis Subversion.

Subversion, förkortat svn, är enkelt uttryckt en databas som innehåller all kod man utvecklar. När jag ska börja utveckla en viss funktion på en sajt ser jag till att hämta hem den senaste versionen av koden från databasen, eller med  korrekta termer, jag checkar ut koden. Jag har nu all kod på min egen dator och utvecklar min funktion och när jag är klar så skickar jag tillbaka koden till databasen, jag gör en commit (eller commitar som vi säger på svengelska). När jag gör det så kontrollerar svn att det inte finns en nyare version av de filer jag editerat, om det finns det så ber servern mig att uppdatera mina filer först. När jag uppdaterar så försöker svn att slå ihop mina utvecklade funktioner med den befintliga koden, och efter det kan jag commita igen. Det fina med det hela är att det är bara filer som är ändrade som överförs, jag behöver alltså inte ladda hem eller ladda upp all kod igen. Om svn inte kan slå ihop mina förändringar med den befintliga koden så får jag lösa det själv genom att jag får se filen i de olika versionerna sida vid sida och kan på så vis bestämma hur slutresultatet ska se ut. Det där beror så klart lite på vilken editor man använder, men de flesta avancerade utvecklingsverktygen har stöd för svn och då fungerar det som jag sa ovan.

En av de absoluta fördelarna med att använda Subversion är att alla versioner av filerna sparas. Man kan alltså när som helst gå tillbaka till vilken version som helst av filen. Säg att jag märker att en viss funktion har slutat fungera, då kan jag enkelt backa till en tidigare version, där jag vet att det fungerade. Ungefär som en flerstegs undo :)

Med hjälp av Subversion kan alltså flera utvecklare arbeta samtidigt på samma kod utan att behöva bry sig om att de andra gör det samtidigt.

En annan väldigt praktisk funktion är något som kallas för taggning. När vi tycker att vi har utvecklat klart och det är dags att publicera det vi gjort kan vi ”tagga” koden. Detta innebär att om jag exempelvis taggar aktuell kod i databasen med v1.0 (första versionen av applikationen) och sedan fortsätter att utveckla, så kommer databasen ändå ihåg exakt hur all kod såg ut vid taggningen. Man kan säga att det skapas en kopia av koden exakt vid ögonblicket för taggningen även om det inte sker i verkligheten. Jag kan nu alltså när jag vill hämta hem version 1.0 av applikationen, även om vi fortsatt utvecklingen och kommit till version 1.5. På det här viset kan vi även buggfixa på version 1.4 samtidigt som utveckling sker på 1.5, vilket underlättar otroligt mycket om version 1.5 innehåller mycket ny funktionalitet.

För dig som använder Mac har tidningen Macworld har skrivit en artikel som går igenom grunderna i Subversion på just Mac.

 

0 kommentarer.