Tips en Trucs 2024

Shellscripts verbeteren en debuggen met ShellCheck

ShellCheck is een gratis en open source analyseprogramma dat kan worden gebruikt om shellscripts te controleren en te verbeteren. Het kan zowel veelvoorkomende als uitzonderlijke fouten markeren en de juiste oplossingen voorstellen. ShellCheck kan worden gebruikt als een online of systeemhulpprogramma, maar kan ook worden geïntegreerd als een linter in verschillende teksteditors.

Shellcheck installeren

Laten we eerst ShellCheck installeren op ons favoriete Linux-systeem. Dit is een zeer eenvoudige taak, aangezien het hulpprogramma is verpakt in de softwarebronnen van de meest gebruikte distributies. We hoeven alleen maar de juiste pakketbeheerder te gebruiken. Op Debian en andere Debian-gebaseerde systemen gebruiken we apt:

dany@pindabook:~$ sudo apt install shellcheck
[sudo] wachtwoord voor root: 
Pakketlijsten worden ingelezen... Klaar
Boom van vereisten wordt opgebouwd... Klaar
De statusinformatie wordt gelezen... Klaar 
De volgende NIEUWE pakketten zullen geïnstalleerd worden:
  shellcheck
0 opgewaardeerd, 1 nieuw geïnstalleerd, 0 te verwijderen en 0 niet opgewaardeerd.
Er moeten 2.621 kB aan archieven opgehaald worden.
Na deze bewerking zal er 19,4 MB extra schijfruimte gebruikt worden.
Ophalen:1 http://deb.debian.org/debian bookworm/main amd64 shellcheck amd64 0.9.0-1 [2.621 kB]
2.621 kB opgehaald in 0s (10,2 MB/s)
Voorheen niet geselecteerd pakket shellcheck wordt geselecteerd.
(Database wordt ingelezen ... 173847 bestanden en mappen momenteel geïnstalleerd.)
Uitpakken van .../shellcheck_0.9.0-1_amd64.deb wordt voorbereid...
Bezig met uitpakken van shellcheck (0.9.0-1) ...
Instellen van shellcheck (0.9.0-1) ...
Bezig met afhandelen van triggers voor man-db (2.11.2-2) ...

Shellcheck gebruiken

Het gebruik van ShellCheck is heel eenvoudig. Meestal hoeven we het alleen maar aan te roepen en het pad van het script dat we willen controleren als argument mee te geven. Een voorbeeld. In het volgende fragment kun je duidelijk zien dat we hebben verzuimd om een shellvariabele te citeren (staat niet tussen aanhalingstekens). Dit is een veelgemaakte fout die, afhankelijk van de omstandigheden, gevaarlijk kan zijn:

#!/bin/bash

tekst="Dit is een tekst."
 
echo $tekst

We slaan de bovenstaande code op in een bestand met de naam script.sh. Om het te controleren met ShellCheck geven we het gewoon als argument door aan het hulpprogramma:

dany@pindabook:~$ shellcheck script.sh

Het resultaat van de bovenstaande opdracht is de volgende:

In script.sh line 5: echo $tekst ^----^ SC2086 (info): Double quote to prevent globbing and word splitting. Did you mean: echo "$tekst" For more information: https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...

Zoals je kunt zien, is de fout correct gevonden en gemarkeerd. De fout wordt geïdentificeerd met een specifieke code, die in dit geval SC2086 is, en er wordt een korte beschrijving gegeven. Meer informatie kan worden opgevraagd door op de link te klikken die naar de bijbehorende ShellCheck Wiki-pagina verwijst:

ShellCheck

ShellCheck is onder andere ook in staat om “bashisms” te detecteren: niet-standaard eigenschappen die specifiek zijn voor de Bash shell. We worden gewaarschuwd als we Bash niet expliciet als shell-interpreter specificeren. Kijk bijvoorbeeld eens naar dit voorbeeld:

#!/bin/sh
 
# De huidige datum en tijd weergeven
function now() {
  date '+%Y/%m/%d %H:%M'
}

Als we ShellCheck tegen deze code uitvoeren, krijgen we de volgende uitvoer:

dany@pindabook:~$ shellcheck date.sh

In date.sh line 4:
function now() {
^-- SC2112 (warning): 'function' keyword is non-standard. Delete it.

For more information:
  https://www.shellcheck.net/wiki/SC2112 -- 'function' keyword is non-standar...

Hoewel er geen fouten in de code zitten, waarschuwt ShellCheck ons omdat we het sleutelwoord “function” hebben gebruikt om een functie te maken: deze syntaxis is bash-specifiek, maar we hebben bash niet expliciet opgegeven als de scriptinterpreter (we hebben /bin/sh gebruikt, wat in sommige distributies, zoals Ubuntu, een symbolische link is die naar de “dash” shell wijst).

De online versie van ShellCheck gebruiken

Als we ShellCheck om bepaalde redenen niet op ons systeem kunnen of willen installeren, kunnen we onze scripts online controleren met de webversie van ShellCheck. Het enige wat we hoeven te doen is onze code in de online editor te plakken. Eventuele waarschuwingen verschijnen eronder:

SpellCheck Web

Zoals je in de bovenstaande schermafbeelding kunt zien, verschijnt er ook een teken op de regels waar waarschuwingen of fouten zijn gevonden. Dit gedrag kan worden gerepliceerd in de meeste teksteditors door ShellCheck te integreren als een linter. Laten we eens kijken hoe.

ShellCheck in Kate integreren

ShellCheck kan in een aantal van de meest gebruikte teksteditors worden geïntegreerd als een linter. Om ShellCheck in Kate te integreren is de JavaScript npm ontwikkelomgeving nodig. Dit is een uitgebreid pakket en neemt dus relatief veel schijfruimte in (178 MB). Het npm pakket installeer je met de opdracht:

dany@pindabook:~$ sudo apt install npm
Pakketlijsten worden ingelezen... Klaar
Boom van vereisten wordt opgebouwd... Klaar
De statusinformatie wordt gelezen... Klaar 
De volgende extra pakketten zullen geïnstalleerd worden:
  eslint gyp handlebars libc-ares2 libjs-async libjs-events libjs-inherits libjs-is-typedarray libjs-prettify
  libjs-regenerate libjs-source-map libjs-sprintf-js libjs-typedarray-to-buffer libjs-util libnode-dev libnode108
  libnotify-bin libssl-dev libuv1-dev node-abbrev node-acorn node-agent-base node-ajv node-ajv-keywords
  node-ampproject-remapping node-ansi-escapes node-ansi-regex node-ansi-styles node-anymatch node-aproba
  node-archy node-are-we-there-yet node-argparse node-arrify node-assert node-async node-async-each node-auto-bind
  node-babel-helper-define-polyfill-provider node-babel-plugin-add-module-exports node-babel-plugin-lodash
...
  node-webassemblyjs node-webpack-sources node-which node-wide-align node-widest-line node-wordwrap node-wrap-ansi
  node-wrappy node-write node-write-file-atomic node-ws node-xtend node-y18n node-yallist node-yaml node-yargs
  node-yargs-parser nodejs nodejs-doc terser webpack
Voorgestelde pakketten:
  node-babel-eslint node-esprima-fb node-inquirer libjs-angularjs libssl-doc node-babel-plugin-polyfill-es-shims
  node-babel7-debug livescript chai node-jest-diff
De volgende NIEUWE pakketten zullen geïnstalleerd worden:
  eslint gyp handlebars libc-ares2 libjs-async libjs-events libjs-inherits libjs-is-typedarray libjs-prettify
  libjs-regenerate libjs-source-map libjs-sprintf-js libjs-typedarray-to-buffer libjs-util libnode-dev libnode108
  libnotify-bin libssl-dev libuv1-dev node-abbrev node-acorn node-agent-base node-ajv node-ajv-keywords
  node-ampproject-remapping node-ansi-escapes node-ansi-regex node-ansi-styles node-anymatch node-aproba
  node-archy node-are-we-there-yet node-argparse node-arrify node-assert node-async node-async-each node-auto-bind
  node-babel-helper-define-polyfill-provider node-babel-plugin-add-module-exports node-babel-plugin-lodash
...
  node-webassemblyjs node-webpack-sources node-which node-wide-align node-widest-line node-wordwrap node-wrap-ansi
  node-wrappy node-write node-write-file-atomic node-ws node-xtend node-y18n node-yallist node-yaml node-yargs
  node-yargs-parser nodejs nodejs-doc npm terser webpack
0 opgewaardeerd, 394 nieuw geïnstalleerd, 0 te verwijderen en 0 niet opgewaardeerd.
Er moeten 29,5 MB aan archieven opgehaald worden.
Na deze bewerking zal er 178 MB extra schijfruimte gebruikt worden.
Wilt u doorgaan? [J/n]
Ophalen:1 http://deb.debian.org/debian bookworm/main amd64 node-fast-deep-equal all 3.1.3-3 [5.768 B]
Ophalen:2 http://deb.debian.org/debian bookworm/main amd64 node-json-schema-traverse all 1.0.0-3 [6.308 B]
Ophalen:3 http://deb.debian.org/debian bookworm/main amd64 node-jsonify all 0.0.1-1 [8.704 B]
...
Ophalen:392 http://security.debian.org/debian-security bookworm-security/main amd64 libuv1-dev amd64 1.44.2-1+deb12u1 [172 kB]
Ophalen:393 http://security.debian.org/debian-security bookworm-security/main amd64 libnode-dev amd64 18.19.0+dfsg-6~deb12u1 [503 kB]
Ophalen:394 http://security.debian.org/debian-security bookworm-security/main amd64 nodejs-doc all 18.19.0+dfsg-6~deb12u1 [3.569 kB]
29,5 MB opgehaald in 3s (11,1 MB/s)     
Extraheren van sjablonen uit pakketten: 100%
Voorheen niet geselecteerd pakket node-fast-deep-equal wordt geselecteerd.
(Database wordt ingelezen ... 180327 bestanden en mappen momenteel geïnstalleerd.)
Uitpakken van .../000-node-fast-deep-equal_3.1.3-3_all.deb wordt voorbereid...
Bezig met uitpakken van node-fast-deep-equal (3.1.3-3) ...
...
Voorheen niet geselecteerd pakket npm wordt geselecteerd.
Uitpakken van .../393-npm_9.2.0~ds1-1_all.deb wordt voorbereid...
Bezig met uitpakken van npm (9.2.0~ds1-1) ...
Instellen van libuv1-dev:amd64 (1.44.2-1+deb12u1) ...
Instellen van node-colors (1.4.0-4) ...
Instellen van node-fs.realpath (1.0.0-3) ...
...
Instellen van node-deep-equal (2.1.0+~cs31.12.80-1) ...
Instellen van node-css-loader (6.7.2+~cs14.0.11-1) ...
Instellen van npm (9.2.0~ds1-1) ...
Bezig met afhandelen van triggers voor libc-bin (2.36-9+deb12u7) ...
Bezig met afhandelen van triggers voor man-db (2.11.2-2) ...

Via npm kunnen we nu de bash-language-server installeren die de brug maakt tussen Kate en ShellCheck.

dany@pindabook:~$ sudo npm i -g bash-language-server

added 33 packages in 6s

4 packages are looking for funding
  run `npm fund` for details

In de volgende schermafbeelding zie je de samenwerking:

ShellCheck Kate

ShellCheck kan ook worden geïntegreerd in andere teksteditors, zoals Vim, Visual Studio Code, Sublime Text en Emacs: instructies kunnen worden gevonden in de speciale sectie van de ShellCheck README.

ShellCheck verwijderen

Eerst verwijderen we het npm pakket bash-language-server met de opdracht:

dany@pindabook:~$  sudo npm uninstall -g bash-language-server

removed 33 packages in 257ms

Dan mag de omvangrijke JavaScript ontwikkelomgeving npm verwijdert worden:

dany@pindabook:~$  sudo apt purge npm
Pakketlijsten worden ingelezen... Klaar
Boom van vereisten wordt opgebouwd... Klaar
De statusinformatie wordt gelezen... Klaar 
De volgende pakketten zijn automatisch geïnstalleerd en zijn niet langer nodig:
  eslint gyp handlebars libc-ares2 libjs-async libjs-events libjs-inherits libjs-is-typedarray libjs-prettify
  libjs-regenerate libjs-source-map libjs-sprintf-js libjs-typedarray-to-buffer libjs-util libnode-dev libnode108
  libnotify-bin libssl-dev libuv1-dev node-abbrev node-acorn node-agent-base node-ajv node-ajv-keywords
  node-ampproject-remapping node-ansi-escapes node-ansi-regex node-ansi-styles node-anymatch node-aproba
  node-archy node-are-we-there-yet node-argparse node-arrify node-assert node-async node-async-each node-auto-bind
  node-babel-helper-define-polyfill-provider node-babel-plugin-add-module-exports node-babel-plugin-lodash
...
  node-webassemblyjs node-webpack-sources node-which node-wide-align node-widest-line node-wordwrap node-wrap-ansi
  node-wrappy node-write node-write-file-atomic node-ws node-xtend node-y18n node-yallist node-yaml node-yargs
  node-yargs-parser nodejs nodejs-doc terser webpack
Gebruik 'sudo apt autoremove' om ze te verwijderen.
De volgende pakketten zullen VERWIJDERD worden:
  npm*
0 opgewaardeerd, 0 nieuw geïnstalleerd, 1 te verwijderen en 0 niet opgewaardeerd.
Na deze bewerking zal er 3.012 kB schijfruimte vrijkomen.
Wilt u doorgaan? [J/n] 
(Database wordt ingelezen ... 209620 bestanden en mappen momenteel geïnstalleerd.)
npm (9.2.0~ds1-1) wordt verwijderd ...
Bezig met afhandelen van triggers voor man-db (2.11.2-2) ...
(Database wordt ingelezen ... 208661 bestanden en mappen momenteel geïnstalleerd.)
Configuratiebestanden voor npm (9.2.0~ds1-1) worden gewist ...

Om echt schijfruimte vrij te maken, verwijderen we ook de niet langer gebruikte afhankelijke pakketten met:

dany@pindabook:~$  sudo apt autoremove
Pakketlijsten worden ingelezen... Klaar
Boom van vereisten wordt opgebouwd... Klaar
De statusinformatie wordt gelezen... Klaar 
De volgende pakketten zullen VERWIJDERD worden:
  eslint gyp handlebars libc-ares2 libjs-async libjs-events libjs-inherits libjs-is-typedarray libjs-prettify
  libjs-regenerate libjs-source-map libjs-sprintf-js libjs-typedarray-to-buffer libjs-util libnode-dev libnode108
  libnotify-bin libssl-dev libuv1-dev node-abbrev node-acorn node-agent-base node-ajv node-ajv-keywords
  node-ampproject-remapping node-ansi-escapes node-ansi-regex node-ansi-styles node-anymatch node-aproba
  node-archy node-are-we-there-yet node-argparse node-arrify node-assert node-async node-async-each node-auto-bind
  node-babel-helper-define-polyfill-provider node-babel-plugin-add-module-exports node-babel-plugin-lodash
...
  node-webassemblyjs node-webpack-sources node-which node-wide-align node-widest-line node-wordwrap node-wrap-ansi
  node-wrappy node-write node-write-file-atomic node-ws node-xtend node-y18n node-yallist node-yaml node-yargs
  node-yargs-parser nodejs nodejs-doc terser webpack
0 opgewaardeerd, 0 nieuw geïnstalleerd, 393 te verwijderen en 0 niet opgewaardeerd.
Na deze bewerking zal er 175 MB schijfruimte vrijkomen.
Wilt u doorgaan? [J/n]
(Database wordt ingelezen ... 208661 bestanden en mappen momenteel geïnstalleerd.)
node-css-loader (6.7.2+~cs14.0.11-1) wordt verwijderd ...
webpack (5.75.0+dfsg+~cs17.16.14-1+deb12u1) wordt verwijderd ...
eslint (6.4.0~dfsg+~6.1.9-7) wordt verwijderd ...
...
node-busboy (1.6.0+~cs2.6.0-2) wordt verwijderd ...
node-cjs-module-lexer (1.2.2+dfsg-5) wordt verwijderd ...
node-xtend (4.0.2-3) wordt verwijderd ...
Bezig met afhandelen van triggers voor man-db (2.11.2-2) ...
Bezig met afhandelen van triggers voor libc-bin (2.36-9+deb12u7) ...

En de in deze tip gebruikte scripts:

dany@pindabook:~$ rm script.sh date.sh