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 naarbash5
ofbash4
(dit maakt het ook mogelijk ombash
v4 enbash
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 naarbash5
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!)