Tips en Trucs 2020

Het zwarte gat /dev/null

Technisch is "/dev/null" een virtueel apparaat. Programma's benaderen dit als een echt bestand. Programma's kunnen uit virtuele apparaten gegevens ophalen (lezen). Maar deze gegevens worden niet van een schijf gelezen, maar door het besturingssysteem geleverd. Een ander voorbeeld is het bestand "/dev/zero".

In ons geval gaan we gegevens naar "/dev/null" sturen (schrijven). Maar alles wat naar "/dev/null" wordt geschreven, wordt genegeerd, vergeten, weggegooid. Om het nut daarvan te begrijpen, bekijken we eerst hoe standard output en standard error in Linux werken.

stdout en srderr

Een terminal opdracht kan twee soorten uitvoer produceren. Standaard uitvoer wordt naar stdout gestuurd en foutmeldingen naar stderr.

Standaard worden stdout en stderr geassocieerd met het terminal venster. Dit betekent dat alles wat naar stdout en stderr wordt gestuurd op het scherm wordt weergegeven. Met behulp van shell redirection kan je dit gedrag aanpassen. Zo kan je uitvoer in plaats van weer te geven, doorsturen (redirect) naar een bestand om het later te lezen of te analyseren. Of je kan de uitvoer sturen naar een fysiek apparaat zoals een LED of LCD scherm.

Stdout en stderr doorsturen via redirect:

Gebruik /dev/null om uitvoer die je niet wil, te verwijderen

Daar er twee verschillende soorten uitvoer zijn, willen we één soort filteren. Een voorbeeld: we zoeken naar bestanden in de map /sys/ die iets te maken hebben met energie (power) instellingen.

dany@main:~> grep -r power /sys/  
grep: /sys/kernel/slab/:d-0001024/remote_node_defrag_ratio: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/total_objects: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/alloc_calls: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/cpu_slabs: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/objects: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/objects_partial: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/cpu_partial: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/validate: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/free_calls: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/min_partial: Toegang geweigerd
...
grep: /sys/module/nvidia_modeset/sections/.note.gnu.build-id: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.text: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.data: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.altinstr_replacement: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.smp_locks: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/__bug_table: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.rodata.str1.1: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/__ksymtab_strings: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.altinstr_aux: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.rodata.str1.8: Toegang geweigerd

Door het enorme aantal bestanden die niet voor een gewone gebruiker toegankelijk zijn, krijg je massa's foutmeldingen. Deze foutmeldingen zorgen ervoor dat het bijna onmogelijk is om de informatie die we willen zien, te vinden. Daar "Toegang geweigerd" foutmeldingen via stderr worden weergegeven, kan je ze met de opdracht grep -r power /sys/ 2>/dev/null naar "/dev/null" sturen.

stderr naar /dev/null sturen

Zoals je ziet, is dit veel leesbaarder.

In andere gevallen zijn enkel de foutmeldingen belangrijk. Een voorbeeld: om een netwerkverbinding te testen wordt dikwijls de ping opdracht gebruikt:

dany@main:~> ping google.com
PING google.com(par10s28-in-x0e.1e100.net (2a00:1450:4007:80a::200e)) 56 data bytes
64 bytes from par10s28-in-x0e.1e100.net (2a00:1450:4007:80a::200e): icmp_seq=1 ttl=118 time=18.0 ms
64 bytes from par10s28-in-x0e.1e100.net (2a00:1450:4007:80a::200e): icmp_seq=2 ttl=118 time=17.6 ms
64 bytes from par10s28-in-x0e.1e100.net (2a00:1450:4007:80a::200e): icmp_seq=3 ttl=118 time=17.6 ms
64 bytes from par10s28-in-x0e.1e100.net (2a00:1450:4007:80a::200e): icmp_seq=4 ttl=118 time=17.8 ms
^C
--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 17.640/17.809/18.032/0.227 ms

Deze opdracht blijft doorlopen tot je ze afsluit met de sneltoets Ctrl+c. De ping opdracht toont informatie over elke verbindingspoging, maar soms is het handiger om enkel de foutmeldingen weer te geven. We verwijderen de standaard uitvoer door deze naar het "/dev/null" apparaat te sturen:

dany@main:~> ping google.com 1>/dev/null
ping: sendmsg: Netwerk is onbereikbaar
ping: sendmsg: Netwerk is onbereikbaar
ping: sendmsg: Netwerk is onbereikbaar
ping: sendmsg: Netwerk is onbereikbaar
ping: sendmsg: Netwerk is onbereikbaar

Je krijgt nu enkel nog de foutmeldingen, namelijk bij netwerkonderbrekingen en dergelijke. De geslaagde verbindingen zien we niet langer, waardoor de focus op het opsporen van netwerkproblemen ligt.

Je kunt de standaard uitvoer en foutmeldingen ook naar verschillende locaties sturen. In het volgende voorbeeld zien we niets op het scherm, de standaarduitvoer wordt namelijk verwijdert en de foutmeldingen opgeslagen in het bestand error.log:

dany@main:~> ping google.com 1>/dev/null 2>error.log
^Cdany@main:~> cat error.log 
ping: sendmsg: Netwerk is onbereikbaar
ping: sendmsg: Netwerk is onbereikbaar
ping: sendmsg: Netwerk is onbereikbaar
ping: sendmsg: Netwerk is onbereikbaar
ping: sendmsg: Netwerk is onbereikbaar
ping: sendmsg: Netwerk is onbereikbaar
dany@main:~> rm error.log

Alle uitvoer naar het zwarte gat sturen

Soms is het handig om alle uitvoer te verwijderen. Dit kan op twee manieren.

dany@main:~> grep -r power /sys/ >/dev/null 2>&1

Met >/dev/null stuur je de standaard uitvoer naar "/dev/null" en 2>&1 stuurt de foutmeldingen (stderr) naar de standaard uitvoer (stdout). Hier gebruiken we &1 in plaats van gewoon 1, omdat je met 2>1 de standaard uitvoer naar het bestand met de naam "1" zou sturen.

Ook de volgorde is belangrijk, bij het omkeren van de redirect parameters, krijg je een heel ander resultaat.

dany@main:~> grep -r power /sys/ 2>&1 >/dev/null
grep: /sys/kernel/slab/:d-0001024/remote_node_defrag_ratio: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/total_objects: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/alloc_calls: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/cpu_slabs: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/objects: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/objects_partial: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/cpu_partial: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/validate: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/free_calls: Toegang geweigerd
grep: /sys/kernel/slab/:d-0001024/min_partial: Toegang geweigerd
...
grep: /sys/module/nvidia_modeset/sections/.note.gnu.build-id: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.text: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.data: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.altinstr_replacement: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.smp_locks: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/__bug_table: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.rodata.str1.1: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/__ksymtab_strings: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.altinstr_aux: Toegang geweigerd
grep: /sys/module/nvidia_modeset/sections/.rodata.str1.8: Toegang geweigerd

Bij het interpreteren van 2>&1 worden de foutmeldingen (stderr) naar de standaard uitvoer (stdout) gestuurd en op het scherm weergegeven. Daarna wordt de standaard uitvoer (stdout) verwijderd door deze naar "/dev/null" te sturen. Het resultaat is dat je de foutmeldingen op het scherm ziet verschijnen en niet alle uitvoer wordt onderdrukt. Heb je moeite om de correcte volgorde te onthouden, gebruik dan de volgende alternatieve opdracht om alle uitvoer te onderdrukken:

dany@main:~> grep -r power /sys/ &>/dev/null

De parameter &>/dev/null zorgt dat beide uitvoertypes naar het zwarte gat worden gestuurd.

Nog meer voorbeelden

Veronderstel dat je de sequentiële leessnelheid van een schijf wilt meten. De test is niet zeer nauwkeurig, maar nauwkeurig genoeg. We gebruiken de dd opdracht die de uitvoer zowel naar stdout als een bestand kan schrijven. Je kunt dd dus ook naar het virtuele bestand "/dev/null" laten schrijven. De dd parameter of=/dev/null zorgt daarvoor. Je hoeft dus niet eens van redirection gebruik te maken. De if= parameter bepaald welk bestand je wilt lezen, om het vervolgens naar het bestand vermeld bij of= te schrijven.

dany@main:~> dd if=Downloads/systemrescue-7.01-amd64.iso of=/dev/null status=progress bs=1M iflag=direct
593494016 bytes (593 MB, 566 MiB) copied, 3 s, 197 MB/s
699+0 records gelezen
699+0 records geschreven
732954624 bytes (733 MB, 699 MiB) copied, 3,70987 s, 198 MB/s

Je kunt deze truc ook gebruiken om de downloadsnelheid van een server te bepalen, zonder iets naar een bestand te schrijven. Schrijf het gedownloade bestand gewoon naar "/dev/null".

dany@main:~> wget -O /dev/null https://osdn.net/projects/systemrescuecd/storage/releases/7.01/systemrescue-7.01-amd64.iso
--2020-12-27 15:05:54--  https://osdn.net/projects/systemrescuecd/storage/releases/7.01/systemrescue-7.01-amd64.iso
Herleiden van osdn.net (osdn.net)... 202.221.179.17
Verbinding maken met osdn.net (osdn.net)|202.221.179.17|:443... verbonden.
HTTP-verzoek is verzonden; wachten op antwoord... 302 Found
Locatie: https://osdn.net/frs/redir.php?m=dotsrc&f=%2Fstorage%2Fg%2Fs%2Fsy%2Fsystemrescuecd%2Freleases%2F7.01%2Fsystemrescue-7.01-amd64.iso [volgen...]
--2020-12-27 15:05:55--  https://osdn.net/frs/redir.php?m=dotsrc&f=%2Fstorage%2Fg%2Fs%2Fsy%2Fsystemrescuecd%2Freleases%2F7.01%2Fsystemrescue-7.01-amd64.iso
Verbinding met osdn.net:443 wordt hergebruikt.
HTTP-verzoek is verzonden; wachten op antwoord... 302 Found
Locatie: https://dotsrc.dl.osdn.net/osdn/storage/g/s/sy/systemrescuecd/releases/7.01/systemrescue-7.01-amd64.iso [volgen...]
--2020-12-27 15:05:55--  https://dotsrc.dl.osdn.net/osdn/storage/g/s/sy/systemrescuecd/releases/7.01/systemrescue-7.01-amd64.iso
Herleiden van dotsrc.dl.osdn.net (dotsrc.dl.osdn.net)... 2001:878:346::116, 130.225.254.116
Verbinding maken met dotsrc.dl.osdn.net (dotsrc.dl.osdn.net)|2001:878:346::116|:443... verbonden.
HTTP-verzoek is verzonden; wachten op antwoord... 200 OK
Lengte: 732954624 (699M) [application/octet-stream]
Wordt opgeslagen als: ‘/dev/null’

/dev/null                         100%[==========================================================>] 699,00M  9,79MB/s    in 67s      

2020-12-27 15:07:03 (10,4 MB/s) - '‘/dev/null’' opgeslagen [732954624/732954624]