Categoriearchief: bash

verwijderen van git branches en tags

Met regelmaat zal je een branch verwijderen in git. Lokaal is dit eenvoudig:

# verwijder een lokale branch
git branch -d <branch>

Maar remote is dat een iets complexer verhaal:
Gebruik je een versie ouder dan 1.7.0, dan is dit het antwoord:

# verwijder een remote branch, oude stijl
git push origin :<branch>

Niet echt duidelijk wat er nu gebeurd, daarom vanaf versie 1.7.0:

# verwijder een remote branch, nieuwe stijl
git push --delete origin <branch>

Voor tags is de syntax bijna hetzelfde:

# verwijder lokale tag
git tag -d <tag>

# verwijder remote tag in versie's ouder dan 1.7.0
git push origin :refs/tags/<tag>

# verwijder remote tag in versie's vanaf 1.7.0
git push --delete origin <tag>

Tenslotte worden remote branches ook wel eens door anderen verwijderd. Dit wordt niet automatisch bijgewerkt door git wanneer je pullt of fetched.
Ook hiervoor is een simpele methode om dit bij te werken:

# update de lokale database van remote branches
git remote prune origin

En daarmee staat weer een stukje van mijn geheugen online :).

git gebruiken bij het live zetten van nieuwe versies

Wanneer je regelmatig wijzigingen doet aan een applicatie die op meerdere computers draait, is het prettig dat dit makkelijk bijgewerkt kan worden. Dit kan je doen door tags te maken en bij het updaten de laatste tag op te zoeken. Groot nadeel hiervan is echter wel dat je op een gegeven moment een heleboel tags hebt die je niet meer gebruikt.

Een betere oplossing is een wandelende verwijzing naar welke versie je op dit moment wil gebruiken. Hiervoor is een branch meer geschikt. Tags zijn immers niet bedoeld om te verplaatsen.

Kortom, we maken een branch aan dit enkel gebruikt wordt om de versie aan te wijzen welke in productie gebruikt moet worden. Dit natuurlijk in je ontwikkelomgeving.

git branch production
git push -u origin production

Elke keer als je de versie wil wijzigen die in productie gebruikt moet worden wil wijzigen verplaats je de branch. Hoe je dat doet maakt niet zoveel uit, maar meestal zal het een merge zijn waarvoor fast-forward mogelijk is. Je branch production zal dus meestal achter je master aanlopen.

Op de locatie waar de code daadwerkelijk gebruikt wordt kan dan vrij simpel gecontroleerd worden of er een wijziging is:

# zorg dat de remote informatie bijgewerkt is
git fetch origin

# vind de hash van de huidige commit die actief is
commithead=`git rev-parse HEAD`

# vind de hash van de commit van de laatste versie
commitprod=`git rev-parse origin/production`

Het ophalen van de hashes maakt het in bash eenvoudig om te zien of de branch verplaatst is zonder een diff te hoeven opvragen.

Het opvragen van de verschillen kan alsvolgt:

if [ "${commithead}" != "${commitprod}" ]
then
    # toon een samenvatting van de wijzigingen
    git diff ${commithead} ${commitprod} --stat

    # toon een compleet overzicht van de wijzigingen
    git diff ${commithead} ${commitprod}

    # checkout nieuwe wijzigingen
    git checkout origin/production
fi

In een iets uitgebreider script werkt dit natuurlijk beter. Maar het idee is zo simpel als dit.

resultaat script afvangen

Bij het schrijven van bash script gebruik je uiteraard weer andere scripts in je eigen script (je kopieert toch niet elke keer dat zelfde stukje code??).
Om te beoordelen of een “sub”script goed is uitgevoerd moet je naar de exitcode van het script kijken, dit kan door gebruik te maken van de variabele $?.

ls -l
if [ $? -gt 0 ]
then
    # exit code is groter dan 0, dus een fout trad op
else
    # exit code is 0, alles ok
fi

Wat je precies met het resultaat doet is natuurlijk afhankelijk van je script.
Let wel op dat bij elk volgend uitgevoerd commando de variabele opnieuw ingesteld wordt. Ook wordt de uitvoer van het commando niet afgevangen. Dat kan je eventueel ondervangen door hetvolgende te doen:

output=`ls -l`
resultcode=$?

Je hebt nu 2 variabelen. $output bevat de output van het commando, $resultcode bevat de errorcode.

linux bash script interactief of niet?

Scripts onder linux bash kunnen op verschillende manieren gestart worden. De gebruiker kan handmatig het script starten met een druk op de knop. Maar wat vaker gebeurd is dat een script gestart wordt door linux zelf zonder tussenkomst van de gebruiker. Dit zal meestal een geplande cronjob zijn.
Groot verschil hierin is of de gebruiker input kan geven, bij afwezigheid van een gebruiker kan je in een script lang wachten op antwoord. Ook is het soms handiger om minder output te geven in een niet-interactief script. Hoewel foutmeldingen wel prettig zijn is “algemene voortgang” minder relevant, er zit immers niemand naar te kijken.

Uitvinden of het script interactief is is heel simpel:

if [ -z $PS1 ]
then
    # interactief
else
    # niet interactief
fi

wat is de huidige gebruiker in een linux bash script?

Soms heb je een bash script wat uitgevoerd moet worden door root, of juist door een andere specifieke gebruiker. Elke keer opletten of je met de juiste user het script start is iets wat snel misgaat. Dus controleren in het script wordt uitgevoerd met de juiste user is geen overbodige luxe.

Er zijn meerdere manieren om te bepalen wie de huidige user is, het meerst voor de hand ligt het commando `id`:

# toon lijst met informatie
id
### >> uid=0(root) gid=0(root) groups=0(root)

Maar dat is niet echt prettig om te verwerken, gelukkig zijn er parameters.

# toon user id
id -u
### >> 0

# toon primaire group id
id -g
### >> 0

# toon de id's van alle groepen waar de user lid van is
id -G
### >> 0

Als extra parameter kan -n worden meegegeven waarmee niet het id, maar de naam wordt getoond.

Bij het controleren of de huidige user root is is het niet verstandig om te kijken naar de username “root”. De username zou gewijzigd kunnen zijn. Verstandiger is om te kijken naar het userid 0.

Er zijn ook nog alternatieven.
Het commando `whoami` is ook een optie, maar die is beperkter en komt feitelijk neer op het commando `id -un`.

bash script, in welke directory staat dit script?

Bij het schrijven van een bash script in Linux is het soms nodig om te weten wat de directory is waar het script in staat. Relatief gebruik van paden werkt dan niet goed omdat je of het absolute pad moet meegeven als parameter of om dat relatief bepaald wordt aan de hand van de directory waarvandaan het script werd gestart.

Maar hoe kom je daarachter?
Het blijkt heel simpel te bepalen te zijn met de volgende combinatie van commando’s:

readlink -f ${0} | xargs dirname

Let wel op dat dit geen “/” aan het einde van de directory geeft, die moet je eventueel zelf nog toevoegen als je die nodig hebt.

In bash scripts waar ik dit nodig heb zie je vaak de volgende constructie staan:

scriptdir="`readlink -f ${0} | xargs dirname`/"

# ergens verderop
${scriptdir}/../../relatief/script.sh

Hierdoor hoef ik het maar 1x te bepalen en kan ik daarna simpelweg de variabele gebruiken. Qua snelheid zal het niet veel uitmaken, maar leesbaarder is het zeker.