De standaard bash op macOS is nog steeds bash v3:

$ bash --versionGNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)Copyright (C) 2007 Free Software Foundation, Inc.

Nog niet zo lang geleden werd bash v5 uitgebracht. De discrepantie komt van het feit dat bash gelicenseerd is als GPL v3 sinds versie 4. Apple levert geen hulpprogramma’s met een GPL v3-licentie bij macOS.

Niets weerhoudt je er echter van om de nieuwste bash-versie te downloaden en te installeren.

Nieuwe functies zijn onder andere geassocieerde arrays (d.w.z. woordenboeken) en betere auto-aanvul-setup.

Hoewel je zou denken dat dit een veel voorkomende wens is, verwijzen de meeste pagina’s die ik heb gevonden simpelweg naar Homebrew om een nieuwere bash-versie te downloaden en te installeren.

De grootste uitdaging bij het gebruik van brew is dat het niet werkt op de schaal die MacAdmins nodig hebben. brew is ontworpen voor installatie door één gebruiker, waarbij de gebruiker beheerdersrechten heeft. brew’s workflows zijn niet schaalbaar voor grote implementaties die worden gecontroleerd met een beheersysteem.

Eigenlijk zou er een package installer zijn voor de nieuwste bash versie. Helaas biedt het bash-project er geen.

In deze post zal ik laten zien hoe u de nieuwste bash-versie kunt installeren zonder brew en hoe u een installatiepakket kunt bouwen voor implementatie.

Handmatige installatie

Dit vereist dat Xcode of de Developer Command Line Tools worden geïnstalleerd.

Download eerst de broncode voor de nieuwste bash-versie van deze pagina. Op het moment van schrijven is de laatste versie bash-5.0 en het bestand dat u wilt bash-5.0.tar.gz. Eenmaal gedownload, kunt u het archief in Finder uitbreiden door te dubbelklikken.

Update: Ik heb een post met wat bijgewerkte instructies om de patches voor bash 5.0 op te nemen.

Open een Terminal venster en verander van directory naar de zojuist uitgebreide bash-5.0 directory. Start dan het configure script daar.

$ cd ~/Downloads/bash-5.0$ ./configure

Het configureer proces zal een tijdje duren, er zullen veel berichten zijn die de voortgang laten zien.

Als het configure proces eenmaal klaar is. kunt u bash bouwen met het make commando.

$ make

Dit zal de bash binary en de ondersteunende bestanden in de huidige directory bouwen. Dat is niet waar we het uiteindelijk willen hebben, maar het is waarschijnlijk een goed idee om te kijken of het bouwproces werkt. Dit zal (weer) een tijdje duren. Er zullen wat vreemd uitziende waarschuwingen zijn, maar die kunt u negeren.

Wanneer make slaagt, kunt u bash v5 daadwerkelijk installeren met

$ sudo make install

Dit bouwt en installeert de bash binary en ondersteunende bestanden in /usr/local/bin en /usr/local. sudo is nodig om /usr/local aan te passen.

Als u alleen maar op zoek was naar een manier om bash v5 te installeren zonder brew, dan bent u klaar.

Er staat echter meer nuttige informatie in de rest van de post, dus blijf lezen.

Hoe de nieuwe en de oude bash samenwerken

De standaard bash v5 binary heet bash en wordt geïnstalleerd in /usr/local/bin. De macOS standaard PATH vermeldt /usr/local/bin voor /bin waar de standaard bash v3 binary, ook bash genaamd, zich bevindt.

Dit betekent, dat wanneer een gebruiker bash in een shell typt, de versie in /usr/local/bin de voorkeur zal krijgen boven de voorgeïnstalleerde bash v3.

U kunt dit gedrag testen in Terminal. Aangezien de standaard shell nog niet is gewijzigd van /bin/bash opent de Terminal nog steeds naar bash v3. U kunt dit testen door de BASH_VERSION omgevingsvariabele te tonen:

$ echo $BASH_VERSION3.2.57(1)-release

Maar wanneer u dan bash uitvoert, zal het /usr/local/bin/bash aanroepen, dus het zal de nieuwe bash v5 uitvoeren. Het zal dit tonen in de prompt, maar u kunt ook de BASH_VERSION controleren.

$ bashbash-5.0$ echo $BASH_VERSION5.0.0(2)-release

Dit zou de setup kunnen zijn die u wilt, wanneer u bash v5 altijd wilt gebruiken. Het zou echter voor sommige gebruikers tot onverwacht gedrag kunnen leiden.

Eén optie om deze dubbelzinnigheid te vermijden is om de binary in /usr/local/bin te hernoemen naar bash5. Maar dan zullen andere hulpprogramma’s zoals env (hieronder vermeld) de binary niet meer vinden.

  • Scripting OS X: Waar PATHs vandaan komen

Note: de PATH in andere contexten zal waarschijnlijk geen /usr/local/bin bevatten en de zaken verder verwarren.

bash v5 en Scripting

Scripts die bash gebruiken, moeten het volledige pad naar het binary in de shebang hebben. Op deze manier kan de script auteur bepalen of een script wordt uitgevoerd door de standaard bash v3 (/bin/bash) of de nieuwere bash v5 (/usr/local/bin/bash of /usr/local/bin/bash5).

Het wordt vaak aangeraden om het env commando in de shebang te gebruiken:

#!/usr/bin/env bash

Het env commando bepaalt het pad naar de bash binary in de huidige omgeving. (d.w.z. gebruikmakend van de huidige PATH) Dit is handig wanneer het script in verschillende omgevingen moet draaien waar de locatie van de bash binary onbekend is, met andere woorden over meerdere Unix en Unix-achtige platformen. Echter, dit maakt de werkelijke versie van bash die het script zal interpreteren onvoorspelbaar.

Bij voorbeeld, stel u heeft bash v5 geinstalleerd in de standaard configuratie (als /usr/local/bin/bash. Een script met de shebang #!/usr/bin/env bash dat wordt gestart in de gebruikersomgeving (d.w.z. vanuit Terminal) zal de nieuwere bash gebruiken, omdat /usr/local/bin voor /bin komt in de zoekvolgorde.

Wanneer u hetzelfde script in een andere context start, bijvoorbeeld als een installatiescript, een AppleScript, of een beheersysteem, zal /usr/local/bin waarschijnlijk geen deel uitmaken van de PATH in die omgeving. Dan zal de env shebang kiezen voor /bin/bash (v3). Het script zal worden geïnterpreteerd en zich mogelijk anders gedragen.

Administrators geven de voorkeur aan zekerheid in hun beheerde omgevingen. Beheerders moeten de locatie en versies van de binaries op hun systemen kennen. Voor beheerscripts moet u env vermijden en het juiste volledige pad naar de gewenste binary van de interpreter gebruiken.

De oplossingen om de dubbelzinnigheid op te lossen zijn

  • gebruik het volledige pad naar de binary in de shebang
  • manage en update de extra aangepaste versie van bash met een beheersysteem
  • (optioneel) hernoem de nieuwere bash binary naar bash5 of bash4 (dit maakt het ook mogelijk om bash v4 en bash v5 beschikbaar te hebben op hetzelfde systeem)
  • Scripting OS X: Over de Shebang
  • Scripting OS X: Het PATH in Scripts instellen

De standaard Shell van een gebruiker wijzigen in bash v5

Ondanks dat we bash v5 hebben geïnstalleerd, zal de standaard shell van een nieuw Terminal venster nog steeds de ingebouwde bash v3 gebruiken.

Het pad naar de standaard shell is opgeslagen in het gebruikersrecord. U kunt het UserShell attribuut direct wijzigen met dscl, in de ‘Geavanceerde Opties’ van het ‘Gebruikers & Groepen’ voorkeurpaneel, of in Directory Utility.

Er is ook een commando om de standaard shell in te stellen:

$ chsh -s /usr/local/bin/bashChanging shell for armin.Password for armin: chsh: /usr/local/bin/bash: non-standard shell

Het chsh (verander shell) commando zal controleren op toegestane shells in het /etc/shells bestand. U kunt eenvoudig een regel met /usr/local/bin/bash aan dit bestand toevoegen, en dan zal chsh prima werken.

$ chsh -s /usr/local/bin/bashChanging shell for armin.Password for armin: 

Note: als u ervoor kiest om de bash binary te hernoemen, moet u de gewijzigde naam gebruiken in /etc/shells en met chsh.

Onthoud dat alleen het uitvoeren van chsh de shell in het huidige Terminal venster niet zal veranderen. Het is het beste om het oude Terminal venster te sluiten en een nieuw te openen om de nieuwe shell te krijgen.

Bash v5 verpakken voor massa-implementatie

Hoewel deze stappen om bash v5 op een enkele Mac te installeren en configureren eenvoudig genoeg zijn, zouden ze niet goed werken met een beheersysteem voor honderden of duizenden Macs. We willen alle bestanden die make install aanmaakt, verpakken in een package installer payload.

De --help optie van het configure script levert deze nuttige informatie op:

Tot nu toe is make install' will install all the files in/usr/local/bin,/usr/local/libetc. You can specify an installation prefix other than/usr/localusing-prefix, for instance-prefix=$HOME`.

Wanneer we het configure script uitvoeren met de --prefix optie, maakt het een map aan die geschikt is als payload voor een package installer. We kunnen dan pkgbuild gebruiken om te bouwen om een installer pkg te maken:

$ cd ~/Downloads/bash-5.0$ mkdir payload$ ./configure --prefix=/Users/armin/Downloads/bash-5.0/payload$ make install$ pkgbuild --root payload --install-location /usr/local --identifier org.gnu.bash --version 5.0 bash-5.0.pkgpkgbuild: Inferring bundle components from contents of payloadpkgbuild: Wrote package to bash-5.0.pkg

(Opmerking: het --prefix argument vereist een absoluut pad.)

Maak het pakket

Dus, we hebben onze workflow voor het bouwen van een installatiepakket om bash v5 te distribueren en te configureren:

  • download het archief
  • extract het archief
  • run configure met het --prefix argument
  • run make install om de bestanden aan te maken in een payload map
  • optional: hernoem de resulterende bash binary naar bash5 om conflicten te vermijden
  • voeg een postinstall script toe dat /usr/local/bin/bash toevoegt aan /etc/shells indien nog niet aanwezig
  • bouw de installer met pkgbuild

Dit klinkt als een workflow die rijp is voor automatisering. Je kunt het script uit deze repository halen.

Je kunt een ander (geldig) bash versienummer als argument aan het script meegeven, bijv. 4.4.18. (Ik heb niets significant ouder getest.) Het script detecteert niet automatisch de laatste versie en gaat standaard uit van versie 5.0 als er geen argument wordt gegeven. Wanneer een update naar bash v5 wordt gepubliceerd, zult u de versieregel moeten aanpassen of het script met een argument moeten uitvoeren.

Ik heb (nog) niet uitgezocht hoe ik de laatste versie van de download webpagina kan detecteren. Een autopkg recept zal daarop moeten wachten. (Als iemand anders dat wil doen, graag!)

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.