Roligt med mail, at och cron

I en kommande serie i åtminstone åtta delar har jag tänkt beskriva hur min eposthantering ser ut. Det dröjer dock litet. Visserligen vore det en lika hastig som smal sak att bara rapa upp programnamn och konfigurationsfiler, men det vore att ha för låga ambitioner. I stället siktar jag på något den fantastiske författaren Michael W. Lucas skrivit om:

One of the old cliches about writing is that you should “write what you know.” In tech writing this is not only wrong, but actively harmful. … Instead, I recommend writing about something you want to know about.

Det är därför det tar litet tid. Tomrummet som uppstår i väntan på de där inläggen går dock att fylla med små finurligheter som inte egentligen uppfyller några sådana krav. Här kommer ett par av det slaget.

Om du har sendmail eller motsvarande i ordning på din maskin så kan du skicka epost med programmet mail.

Till exempel så här:

$ mail jesper
Subject: Lokalpost
Any fool can paint a picture, but it takes a wise person to be able to
sell it.
EOT

EOT var resultatet av att jag tryckte ^D (vilket betyder CTRL-D). Det här mejlet levereras omedelbart till den lokala användaren jesper, vilket ju är jag själv. Det går förstås även att skicka till en riktig epostadress:

$ mail jesper@example.org
Subject: Globalpost
Pig, n.:
        An animal (Porcus omnivorous) closely allied to the human race
        by the splendor and vivacity of its appetite, which, however, is
        inferior in scope, for it balks at pig.
                -- Ambrose Bierce, "The Devil's Dictionary"
EOT

Men med min konfiguration levereras aldrig det senare mejlet!

En del av förklaringen till detta är att sendmail på min maskin använder en "SMART_HOST", alltså en extern STMP-server som relay, och den servern accepterar inte de här epost-meddelandenas avsändaradress.

Om inget annat anges, så får epost skickade med mail nämligen avsändaren användare@maskin, till exempel "jesper@kaja.mydomain", och relay-servern förkastar mejl från sådana ogiltiga avsändare.

Detta är dock lätt att lösa. Om man matar mail med flaggor efter mottagaradressen, så skickas de vidare till sendmail i stället för att tolkas av mail. För att skicka ett mejl till jesper@example.org med en bestämd avsändaradress gör jag alltså så här:

$ mail jesper@example.org -f fortune@example.org
Subject: Fortune
Top scientists agree that with the present rate of consumption, the
earth's supply of gravity will be exhausted before the 24th century.
As man struggles to discover cheaper alternatives, we need your help.
Please...

                        CONSERVE GRAVITY

Follow these simple suggestions:

(1)  Walk with a light step.  Carry helium balloons if possible.
(2)  Use tape, magnets, or glue instead of paperweights.
(3)  Give up skiing and skydiving for more horizontal sports like
     curling.
(4)  Avoid showers ... take baths instead.
(5)  Don't hang all your clothes in the closet ... Keep them in one big
     pile.
(6)  Stop flipping pancakes
EOT

Förutsatt att avsändaradressen fortune@example.org är giltig kommer det här mejlet levereras.

Och nu börjar det roliga, eller rättare: Nu gör vi oss av med det tråkiga.

Först och främst är jag trött på att varje gång jag vill skicka mejl som de här behöva köra fortune, kopiera och till sist klistra in det i mina mejl. Samma resultat går ju att uppnå på det här viset:

$ fortune -a | mail -s "Kakan säger" jesper@example.org -f fortune@example.org

Observera hur flaggan -s, som bestämmer Subject, ligger före mottagaradressen och därmed tolkas av mail i stället för att skickas vidare till sendmail.

Nästa grej jag är trött på är att skicka de här mejlen manuellt, för att sedan få dem levererade några sekunder senare. Därför skickar jag dem i stället med hjälp av programmet at, vars poäng helt enkelt är att köra ett eller flera kommandon vid en annan tidpunkt än omedelbart:

$ at 07:45
fortune -a | mail -s "Kakan säger" jesper@example.org -f fortune@example.org
^D

Med detta schemaläggs skickandet till klockan kvart i åtta på morgonen, nästa gång hon är så mycket. at förstår även mer avancerade tidsangivelser, exempelvis teatime september 7 som inträffar kl. 16.00 nästkommande 7/9. (Ett tråkigare sätt att uttrycka samma tidpunkt är annars 201209071600).

Men så här roligt vill jag inte bara ha någon gång ibland och på eget initiativ, utan varje dag. Att mejla en fortune till sig själv passar mycket bättre i cron, som finns till för att köra kommandon vid upprepade tillfällen.

Det finns massor av sätt att konfigurera körningar i cron, som något visst datum varje månad, en viss minut varannan timme, varje söndag och så vidare. Jag är dock bara intresserad av klockslaget kvart i åtta varje morgon. För att fixa detta gör jag crontab -e och pular in den här raden:

Att 45 är en minut och 7 en timme är lätt att inse. De tre asteriskerna i sin tur, står i tur och ordning för datum, månad och veckodag.

Det går även att mata in kommaterade listor eller spännvidder. Här är en variant som skickar det där mejlet varje vardagsmorgon klockan kvart i åtta, förutom i juli:

Visserligen är det svårt att tänka sig något roligare innehåll för automatiska mejl än fortune, men det är nog bäst om jag täcker något praktiskt användningsområde också.

urlwatch.sh

För det här avsnittet var jag först inne på att jag skulle reproducera Richard Stallmans oerhört praktiska webbläsare, men kom som tur var på bättre tankar.

Det blir dock något liknande, nämligen en webbövervakningstjänst. För att åstadkomma denna tar jag hjälp av ett gammalt skript som nyligen fick sig en omgång och kom online: urlwatch.sh.

Med en default-konfiguration läser urlwatch.sh in ett godtyckligt antal whitespace-separerade url:er ur filen ~/.urlwatch/urls, drar ned dem med curl, tolkar om dem till plaintext med lynx och sparar resultatet i en cache. Andra gången skriptet körs hämtar det samma sidor igen, skriver ut en diff mellan den föregående och nuvarande versionen av sidorna och uppdaterar sedan cache-kopian.

Det här skriptet vill jag köra från cron ett par gånger om dagen, bland annat för att få en ping via epost när SVT Play slänger upp nya program på vissa adresser, exempelvis http://www.svtplay.se/agenda. De övergav ju RSS när de bytte till ny sajt i somras.

För att åstadkomma detta installerar jag först skriptet:

$ curl -o bin/urlwatch.sh \
https://raw.github.com/simio/scripts/4f1d265852529fab701f1ce817a15611839047a8/urlwatch.sh
$ mkdir ~/.urlwatch
$ echo "http://www.svtplay.se/agenda" > ~/.urlwatch/urls

(Byt hashen i adressen till master för att hämta den senaste versionen.)

Sedan lägger jag till det i min crontab (med crontab -e, igen):

Observera att det där inte ska vara flera rader, utan bara en. När den här crontabben är sparad kommer skriptet köras klockan 06.00, 12.00 och 18.00 varje dag, och utmatningen mejlas till jesper@example.org vare sig den är tom eller inte.

Flaggan -f till urlwatch.sh gör att skriptet rapporterar diffar i ett format som passar bättre i mejl.

Mejlprogram som försöker vara listiga kan förresten sabba det här genom att sortera bort epost med samma avsändare som mottagare. GMail är en sådan skurk. Du behöver i så fall ange en annan avsändaradress.

Det är dock inte som ovan jag egentligen använder skriptet i min crontab. Eftersom jag använder min lokala mailspool ser jag för det första till att rapporterna aldrig lämnar datorn, genom att skicka dem till mitt användarnamn i stället för min epostadress.

Sedan vill jag inte heller ha rapporter när ingenting hänt, vilket blir resultatet om man använder skriptet som ovan. I stället låter jag skriptet själv sköta mejlandet. Som en bonus blir allting därmed mycket mindre komplicerat i crontabben.:

Timangivelsen */2 betyder varannan timme.

Flaggan -m säger åt urlwatch.sh att skicka rapporten som epost i stället. Mottagare kan bestämmas med flaggan -r, men eftersom defaultvärdet är den användare som kör skriptet behöver jag inte använda den.

Default-värdet för avsändaradress är daemon@localhost, men vill du ändra det så ska du lägga till den här raden i filen ~/.urlwatch/config:

Nu är det slut på det roliga.