Køre en opgave på et bestemt tidspunkt eller fast interval (Launchd)

Det er måske ikke hverdagskost, at man har behov for at køre en opgave med en fast interval, men når man så har behov, så skal man kunne vide hvordan.

Hvis man er bekendt med BSD/*nix baserede systemer, så kender man sikkert også til cron. Cron er en tjeneste der gør det muligt at starte forskellige opgaver på forskellige tidspunkter, eller en fast interval. Opgaverne kan opsætte på bruger eller system niveau. MacOS er i familien af BSD baserede systemer og har derfor også cron muligheder.

Apple har i en del år arbejdet på en anden løsning, som de kalder launchd. Det er ikke just cron erstatning i sig selv som sådan. Det er en bredere vifte af funktioner end cron har, men den har også funktioner til at erstatte cron. Og det er disse jeg kommer til at omtale her.

Lad os sige at vi har behov for at kopiere indhold af en mappe og det vil gerne gøre med en fast interval f.eks. hver dag kl. 08.00.

En måde at gøre det på vil være at skrive et kort bash script der kopiere mappens indhold over til en anden mappe. Og bagefter kalder vi dette script hver dag kl. 08.00. Process vil være mere eller mindre det samme for både cron og launchd job.

Så nedenfor har vi et simpel bash script der vil kopiere indhold fra en mappe over i en anden. Der er ingenting fancy over det som sådan, blot for at illustrere funktionaliteten. Vi vil så kalde dette script med launchd en gang om dagen, kl 08.00.

copy.sh der har til formål at kopiere indhold af mappen over i en anden.

Når vi har scriptet på plads, så skal vi ind og se hvordan vi kalder scriptet på det ønskede interval/tidspunkt.

Da copy.sh kun har til formål at kopiere en bruger mappe over til en anden, og involvere ikke noget med resten af systemet, så kan vi nøjes med at lave en launchd opgave, på bruger niveau. Disse handlinger kaldes Agents og alle brugere kan oprette dem for deres egen bruger, ved at lægge en fil i XML format, der slutter på .plist. Filen skal blot ligges i ~/Library/LaunchAgents.

Læg mærke til at Label string skal helst hedde det samme som filen.

Når filen er oprettet og gemt, så er vi klar til at indlæse/starte filen. Man kan gøre det på to måder. Enten ved at indlæse den manuelt, eller genstarte, og så vil den indlæses ved system opstart for denne bruger. Det kan også være man kan nøjes med at logge ud og ind igen. Men dette har jeg ikke lige testet.

Håndtering af Agents

For at indlæse filen uden at genstarte, kan det gøres ved at taste nedenstående kommando i Terminalen.

launchctl load /Users/user1/Library/LaunchAgents/com.nihad.test_copy.plist

Hvis man ikke længere ønsker filen skal køre denne process, så kan man med fordel slå det fra ved at køre denne kommando:

launchctl unload /Users/user1/Library/LaunchAgents/com.nihad.test_copy.plist

StartCalendarInterval kan indeholde en eller flere af nedenstående elementer for at oprette helt præcis kontrol af opstart. Minute, Hour, Weekday, Day, Month.

Fast interval

Man kan udskifte StartCalendarInterval med;

<key>StartInterval</key>
<integer>300</integer>

Hvis man ønsker at starte opgaven med et fast interval, f.eks. 300 sekunder.

Lingon GUI app til alt dette …

Når alt dette er sagt, så findes der faktisk et gratis program, der kan oprette og opsætte disse jobs uden at fifle alt for meget i Terminalen.

Lingon @ Apple App Store

Holde øje med en fil …

Launchd kan også holde øje med en fil, om den bliver ændret, og ud fra det, køre en kommando. Men det må være en anden gang jeg skriver om det.

Erstatning for TimeCapsule

Vi har en TimeCapsule vist en 4. generation af slagsen, som er begyndt at opføre sig underligt på det seneste.

Den vil ud af det blå, miste forbindelse til internettet. Vores enheder vil stadig være koblet på dens accesspoint, men dioden på TimeCapsule, ville blinke orange. Vores AppleTV, der er koblet direkte til vores internet router, vil stadig fungere fint. Så den havde forbindelse til internet, og dermed var det ikke udfald på internettet. Men kun på TimeCapsule. Har forsøgt at udskifte kabler og porte mellem TimeCapsule og routeren, uden at det har lyst problemet.

Så nu har jeg konkluderet at det nok er ved at være tid at udskifte TimeCapsule med noget andet. Apple er holdt op med at producere TimeCapsules, så det skal ikke være TimeCapsule 5. generation.

Men, hvad er der så tilbage af alternativer.

Der er vel to scenarier;

  • En nyt trådløs dims, der kan være en router og hvor der kan kobles en disk til.
  • Bruge udbyderens router og dens wi-fi, og droppe helt TimeMachine backups, og kun have backup i iCloud, som vi allerede har.

Men, hvad skal man vælge hvis man nu skulle have den første scenarie?

MacBook Pro (early 2015) udskiftning af SSD

Min kones Macbook Pro 13″ (Early 2015 model) var kommet med 128GB, da vi på det tidspunkt, skønnede det vil være nok til at starte med. Men det holdt ikke længe, og vi har ret hurtigt skulle supplere pladsen med en SD kort på 128GB, hvor jeg læste det kunne være en mulighed at holde billeder og dokumenter på, der ikke tilgås ofte.

Men da hendes Photos biblioteket er fyldt med alt muligt og fylder 30-40GB så er til tider meget langsomt at arbejde eller finde billeder.

Så, nu hvor der er kommet lidt flere løsninger gik jeg i gang med at undersøge markedet for efter montering af SSD i denne model.

Når man søger på nettet, så få man OWC (Other World Computing) løsning, og nogle få nævner også Transcend’s JetDrive løsning. Da OWC er amerikansk, og dyrt til selve køb i US, uden at medregne hvad told og moms vil koste ved import til Danmark, så OWC skrottet som en løsning. Desuden blev der også nævnt at deres diske var ikke af særlig god kvalitet.

Så kastede jeg blikket mod den europæiske produceret Transcend og deres Jedrive. Og jeg var lige ved at købe det, da jeg læste om en kinesisk adapter der kan konvertere almindelig m.2 SSD diske til at kune arbejde med MacBook Pro.

Så blev der brugt lidt mere tid på undersøgelse af denne løsning, og mens jeg gjorde det, fandt jeg en video der sammenligner Apples SSD, Transcend JetDrive og Samsungs 960 og 970 Evo (begge tilsluttet med adapter).

Og hastigheden på den Transcend JetDrive var så skuffende at jeg var alene med den eneste løsning. Og det er at købe den kinesiske adapter og en Samsung 970 Evo SSD.

I går ankom adapteren fra Kina, og for 2 dage siden fik jeg købt Samsungs 970 Evo. Lige før sengetiden, sat jeg maskinen til at lave en fuld backup på TimeMachine og en klon af disken med SuperDuper!.

TimeMachine skulle jeg bruge til at have en backup af maskinen, hvis der skal gå helt galt. Og jo flere backup muligheder desto bedre. Og SuperDuper! kopi af disken, skulle jeg egentlig bruge til at overføre data fra den gamle Apple SSD disk, over i den nye Samsung, hvis alt gik efter planen.

Så, TimeMachine backup var klar, SuperDuper! disk var også klar og var bootable, så alt er klar.

Slukkede for maskine, åbnede bundplade, afmonterede batteri stik til logicboard, blot for at være på den sikre side, og så ellers putte, Samsungs SSD ind i adapter og de to samlet ind i maskinen, i stedet for Apples SSD.

De tog ikke mere end et minut, og så var det overstået. Tilbage med bagpladen og tand for maskinen…

Da Samsung SSD er totalt tom, er der ingen OS på den, så maskinen startes med at holde ALT nede, for at komme til Recovery mulighed.

Her kan man så installere fra nettet af, nyt OS. Men, ikke her. Og årsagen ligger i, at maskinen er kommet med Yosemite (Mac OS X 10.10) og det er denne Internet Recovery OS der hentes. Udfordring her ligger i, at Yosemite havde ikke understøttelse til NVMr diske, som Samsungs SSD’en er. Derfor, skulle jeg boote ind fra min SuperDuper! backup disk, og tjekke om den finder disken, så jeg kan formatere den og lave en klon. Altså, klone data fra SuperDuper! disken, over til den nye Samsung 970 Evo. Og dette vil virke, fordi, med introduktion af Sierra, har Apple givet mulighed for NVMe diske.

Det tog under en halvtime at overføre data, og så var den klar til at blive testet…

For at opsummere, så har jeg fået data fra den gamle Apple SSD over til Samsungs EVO, ved at kopiere den over fra SuperDuper! Og nu skal vi se om det virker…

Så sluk for maskinen, koble min ekstern disk med SuperDuper! klon ud, og start den, se om der er liv i den… Og det var der…

 

Så ud fra denne test, er der ca 160% forøgelse i skrive hastighed, og 50% forøgelse i læse hastighed.

 

Hvad skal man bruge?

Find dubletter og slet dem

For lidt tid siden var jeg i gang med at overføre alle mine filer fra min gamle mac til den nye. Her opdagede jeg at jeg egentlig har en del filer der synes at være dubletter. Specielt billeder i iPhoto/Photos. Jeg har ved samme lejlighed valgt at uploade alle mine billeder over på min flickr konto, og her var flickr uploader i gang at frasortere dubletter. Den gjorde et ok stykke arbejde, men der var stadig en del filer der ikke blev betragtet som dubletter. Men dette program, slettede heller ikke filer på min mac. Den ville bare ikke uploade dubletter. Så jeg var langt fra løsningen, om at komme dubletter til livs.

Jeg søgte så efter diverse programmer til formålet, og efter at afprøve alle gratis programmer, der ikke duede noget, besluttede jeg at købe programmet Gemini. Hvorfor jeg købte dette og ikke et af de mange andre, ved jeg ikke helt. Men, jeg havde har i længere tid haft god erfaring med CleanMyMac (både 2 og 3) og mente at deres program måtte jo kunne også gøre det ligeså godt som CleanMyMac. Det var trods alt, samme udvikler. Den fandt også nogle flere dubletter og dem fik jeg slettet. Men… jeg synes stadig at der var en del tilbage efterfølgende.

Så måtte jeg ligesom i gang om at finde ud af, hvordan jeg selv kan gøre det. Jeg vidste i forvejen at man kunne udregne et værdi (hash) af filen, der tager i betragtning filens størrelse. Og ville se om ud fra denne værdig jeg kan lige finde alle de filer der er dubletter…

Ud fra 17000+ billeder i min Pictures mappe, var der 4300+ der var dubletter. Altså, efter Gemini var færdig med at finde og slette dubletter.

Gemini fortæller mig, der ikke findes dubletter
Gemini fortæller mig, der ikke findes dubletter

Så nu gik jeg i gang med at undersøge om de dubletter, min process har fundet, er egentlig dubletter, så jeg plukkede 200 tilfældige dubletter og tjekkede op på dem. Alle var rigtige nok. Dermed konkluderede jeg at det må være måden, hvordan man kan finde dubletter.

Nu skal jeg finde en måde, hvordan de kan slettes. Først ville jeg lave det sådan at man bliver præsenteret med filerne og derved vælge hvilken en der skal slettes. Men, efter jeg har lavet 30-40% af det, besluttede jeg, at det er måske overkill at gøre sådan. Så jeg nøjedes blot med at slette en af kopi. Det kan sgu være ligegyldig hvilken en jeg slettede. De var kun nøjagtige kopier den fandt, så selv den mindste ændring vil resultere andet hash-værdi.

Så min fremgangsmåde endte med at bruge lidt bash og PHP, for at slette dubletter. Det kan sikkert laves med andre scripting sprog, men det var disse jeg var fortrolig med og derfor brugte jeg dem. Desuden, findes de som standard på OS X, og derfor noget der kan måske genbruges af andre.

Nedenstående er bash script jeg har kaldt “finger.sh” i det at den beregner en fingeraftryk af hver fil den er sat til at undersøge. Her var det billeder. Men det kan ligeså godt have været andre filer.

echo "Generating MD5 hashes..."
## find all file that have given extensions and generate md5 hash. save output to fingerprint.csv file
## replace "Picture" from below line to reflect folder name you want to check for duplicates.
find −E Pictures −type f −regex ".*.(jpg|gif|png|jpeg|psd|CRW)" −exec md5 {} ; > fingerprint.csv
echo "Almost done... Let's make it nice CSV file"
sFIND="MD5 (" ; sREPLACE=""; cat fingerprint.csv | sed −e "s/$sFIND/$sREPLACE/g" > tmp.csv
sFIND=") = " ; sREPLACE="; "; cat tmp.csv | sed −e "s/$sFIND/$sREPLACE/g" > fingerprint.csv
rm −f ./tmp.csv
echo "Generate list of files to delete..."
php read.php
echo "List is done. Now deleting... no turning back now..."
echo "Deleting..."
#xargs −a delete.txt −d'n' rm
echo "Deleting done. Program exiting..."

Og her er så koden til PHP filen. Den er ikke køn og heller ikke noget der er brugervenligt som sådan. Men det virker efter hensigten. Filen hedder read.php, og denne fil henvises i bash scriptet. Så hvis man vælger at kalde filer noget andet, skal man huske at ændre det i bash filen.

function returndup($arr)
{
return array_diff_key($arr, array_unique($arr));
}

// read CSV into an ARRAY
$file = "/Volumes/Xtra/fingerprint.csv"; // This variable needs to be edited to point to samme directory of read.php file
$csv = file($file);
$arr = array();
for ($i=0; $i < sizeof($csv); $i++) {
$tmp = explode("; ",$csv[$i]);
$arr[$i]["filename"] = $tmp[0];
$arr[$i]['md5'] = $tmp[1];
# create two seperate arrays as well for comparation
$cpFile[$i] = $tmp[0];
$cpMd5[$i] = $tmp[1];
}
$tmp = returndup($cpMd5);
foreach ($tmp as $key => $value) {
$dup[$key]["original"] = $arr[array_search($value, array_column($arr, 'md5'))]["filename"];
$dup[$key]["duplicate"] = $cpFile[$key];
$dup[$key]["md5"] = $cpMd5[$key];
}
while (list($key, $value) = each($dup)) {
$block .= str_replace(" ", " ", $dup[$key]["original"]) ."n";
}
$output .= $block;
file_put_contents('delete.txt', $output);

Hvordan bruges det?

Jeg har puttet finger.sh og read.php filer udenfor mappen Pictures. Det er denne mappe jeg gerne ville gennemsøge for dubletter.
Og så skal man ellers fra Terminal’en køre ./finger.sh (husk finger.sh skal være eksekverbart eg. chmod +x finger.sh) … resten klarer den selv.

OBS: Filerne er indstillet at slette automatisk den ene kopi af dubletter, og det har virket fint for mig. Det skal bruges på egen ansvar, jeg tager ingen ansvar for at man har valgt at køre min kode og fået slettet det der ikke skulle slettes.

Addendum: Som en meget lille sikkerhed, har jeg valgt at kommentere (#) den linie der egentlig sletter dubletter… Man skal fjerne ‘#’ fra den næstsidste linie i finger.sh før den vil slette filer.

LaunchAgents: What’s running?

Often when someone is in need to diagnose troubles with their macs, I need to know what’s running in the background. And what’s starting on boot up. But it’s not easy to get them to tell you that. So I made this small apple script that will collect needed data, copy it into the clipboard and have it ready for pasting.

Download


set SLD to (list folder ("/Library/LaunchDaemons/") without invisibles)
set SLA to (list folder ("/Library/LaunchAgents/") without invisibles)
set ULA to (list folder ((path to home folder as string) & "Library:LaunchAgents") without invisibles)
set x to ""
set SLDL to "System LaunchDaemons :: "
repeat with theItem in SLD
set x to theItem & "
" & x as string
end repeat
set msg to SLDL & x
set x to ""
set SLAL to "
System LaunchAgents :: "
repeat with theItem in SLA
set x to theItem & "
" & x as string
end repeat
set msg to msg & SLAL & x
set x to ""
set ULAL to "
User LaunchAgents :: "
repeat with theItem in ULA
set x to theItem & "
" & x as string
end repeat
set msg to msg & ULAL & x
set the clipboard to msg
display alert "Result copied to clipboard.
Use CMD + V to paste result."