Inleiding tot Bash-shell-omleidingen

  • Eustace Evans
  • 0
  • 2397
  • 245
>

Doelstelling

Leer omleidingen, pijpen en T-stukken te gebruiken in de Bash-schaal

Besturingssysteem en softwareversies

  • Besturingssysteem: - Linux-distributie agnostisch

Voorwaarden

  • Toegang tot een Bash-shell

Moeilijkheidsgraad

GEMAKKELIJK

Conventies

  • # - vereist dat gegeven linux-commando's worden uitgevoerd met root-privileges, hetzij direct als rootgebruiker, hetzij door gebruik van sudo opdracht
  • $ - vereist dat gegeven linux-commando's worden uitgevoerd als een gewone niet-geprivilegieerde gebruiker

Invoering

Omleiding is de mogelijkheid om de invoer en uitvoer van verschillende opdrachten om te leiden van en naar bestanden of apparaten. We gaan zien hoe omleiden werkt in Bash: de standaardshell in de meeste Linux-distributies.

Bestandsbeschrijvingen

Elke keer dat u een programma uitvoert, drie bestandsdescriptors worden standaard gemaakt:
  • 0 - stdin (standaard input)
  • 1 - stdout (standaard output)
  • 2 - stderr (standaardfout)
Standaard is het stdout en stderr descriptors zijn "bijgevoegd" aan het scherm, wat betekent dat de programma-uitvoer en zijn fouten niet in een bestand worden opgeslagen, maar gewoon worden weergegeven, terwijl de standaardinvoer aan het toetsenbord is gekoppeld. Met omleidingsoperatoren kunnen we die associaties manipuleren.

Omleiden van standaarduitvoer

Zoals hierboven vermeld, wordt de standaarduitvoer van een programma standaard naar het scherm gestuurd, maar in sommige omstandigheden, zoals bijvoorbeeld in de context van een script, willen we het misschien weggooien of misschien naar een bestand sturen. Hoe bereiken we dit? De sleutel hier is de> operator:
 ls -l> output.txt 
In dit kleine voorbeeld hebben we de uitvoer van de ls commando naar het bestand output.txt (merk op dat het bestand niet hoeft te bestaan, het wordt automatisch aangemaakt). Er is niets op het scherm verschenen, maar als we de inhoud van het bestand controleren, zien we iets heel bekends:
 $ cat output.txt
totaal 36 drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Desktop drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Documenten drwxr-xr-x. 2 egdoc egdoc 4096 23 juni 02:40 Downloads drwxrwxr-x. 13 egdoc egdoc 4096 23 juni 08:13 git drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Muziek -rw-rw-r--. 1 egdoc egdoc 0 23 juni 09:38 output.txt drwxr-xr-x. 2 egdoc egdoc 4096 22 jun 19:39 Afbeeldingen drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Openbare drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Sjablonen drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Video's
Wat we zien is de output van de ls opdracht. Als we de omleiding nu opnieuw proberen, wordt de huidige inhoud van het bestand vervangen door de nieuwe uitvoer. Hoe kunnen we de vorige inhoud behouden, en rechtvaardig toevoegen nieuwe regels erin? In dit geval gebruiken we de >> operator:
 ls -l >> output.txt 
Op deze manier, als het bestand niet bestaat of geen inhoud heeft, heeft de omleiding hetzelfde effect als wanneer we de > operator, anders wordt de nieuwe inhoud aan de bestaande toegevoegd, zoals u kunt zien door het bestand opnieuw te bekijken:
 totaal 36 drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Desktop drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Documenten drwxr-xr-x. 2 egdoc egdoc 4096 23 juni 02:40 Downloads drwxrwxr-x. 13 egdoc egdoc 4096 23 juni 08:13 git drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Muziek -rw-rw-r--. 1 egdoc egdoc 0 23 juni 09:38 output.txt drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:39 Afbeeldingen drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Openbare drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Sjablonen drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Video's totaal 40 drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Desktop drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Documenten drwxr-xr-x. 2 egdoc egdoc 4096 23 juni 02:40 Downloads drwxrwxr-x. 13 egdoc egdoc 4096 23 juni 08:13 git drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Muziek -rw-rw-r--. 1 egdoc egdoc 541 23 juni 09:38 output.txt drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:39 Afbeeldingen drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Openbare drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Sjablonen drwxr-xr-x. 2 egdoc egdoc 4096 22 juni 19:36 Video's 
Mogelijk moeten we ook de uitvoer van meerdere opdrachten tegelijk omleiden: we kunnen het gewenste resultaat verkrijgen door accolades te gebruiken om ze te groeperen:
$ echo "linuxconfig"; ls -l; > output.txt
Het output.txt-bestand bevat nu zowel de string 'linuxconfig' als het resultaat van het ls -l opdracht.
Een andere veel voorkomende bewerking is om de uitvoer van een commando volledig te negeren, deze keer om te leiden naar een speciaal apparaat: / dev / null. In unix-achtige besturingssystemen / dev / null (ook bekend als bit-bucket), is een apparaat dat alle gegevens die erop zijn geschreven, verwijdert:
ls -l> / dev / null

Leid zowel standaarduitvoer als standaardfout om

In de bovenstaande voorbeelden hebben we zojuist de standaarduitvoer omgeleid. Als er een fout optreedt, kunnen we nog steeds het foutbericht op het scherm zien:
 $ ls -l nonexistingfile.txt> / dev / null ls: heeft geen toegang tot 'nonexistingfile.txt': bestand of map bestaat niet 
Dit gebeurt omdat, zoals hierboven vermeld, stdout en stderr descriptoren zijn volledig door elkaar gescheiden. Wat kunnen we dan doen om ze allebei om te leiden? Er zijn twee syntaxis die we kunnen gebruiken om deze taak te volbrengen: de eerste, die zelfs in oude versies van de shell werkt, is de volgende:
ls -l> output.txt 2> & 1
Wat hebben we gedaan? Allereerst hebben we het stdout van de opdracht naar het output.txt-bestand, net zoals we eerder deden, waarna we de stderr naar de stdout. Let op hoe we naar bestandsdescriptors verwezen met hun respectievelijke nummers. Voor een redelijk moderne Bash-versie kunnen we deze andere, meer gestroomlijnde syntaxis gebruiken:
ls -l &> output.txt

Leid standaarduitvoer om naar standaardfout

Stel je voor dat je een script schrijft en je wilt een case afhandelen wanneer een specifieke instructie mislukt, door de gebruiker een foutmelding te laten zien. Hoe zou je dit bereiken? Het eerste dat in me opkomt, is gewoon echo het gewenste bericht en sluit dan waarschijnlijk het script af met de juiste foutcode. Dit zou prima zijn, maar vraag uzelf af, op welke omschrijving zal dit bericht worden 'verzonden'? Het is de stdout van de echo commando, maar tegelijkertijd, als we dingen vanuit het scriptperspectief bekijken, als een foutmelding, zou het de stderr descriptor. Wat we hier willen doen, is omleiden stdout naar stderr. We gebruiken de volgende syntaxis om de taak uit te voeren:
echo "Er is een fout opgetreden, doei!" > & 2
Het is zeker niet de meest bruikbare foutmeldingen, maar het is genoeg voor ons voorbeeld.

Omleiden van standaardinvoer

Zoals we al eerder zeiden, is de standaardinvoer standaard gekoppeld aan het toetsenbord, maar met behulp van de < operator, kunnen we sommige programma's maken om input van andere bronnen te accepteren. Laten we een snel voorbeeld bekijken met de tr commando (zoals u waarschijnlijk weet tr wordt gebruikt om tekens te verwijderen of te vertalen). Het werkt normaal gesproken als volgt:
tr 'goot tay!' t d
Jij geeft tr een tekenreeks, waarbij u eerst het teken specificeert dat u wilt wijzigen en vervolgens degene die het moet gebruiken om het te vervangen. In dit geval geven we de string 'goot tay!' rechtstreeks, met behulp van het toetsenbord: het wordt vertaald naar 'goede dag!'. Wat we zullen doen om te demonstreren stdin redirection, is om de string naar een bestand te schrijven en vervolgens de inhoud van het bestand om te leiden naar het stdin van de tr opdracht. Eerst schrijven we 'goot tay!' naar het output.txt-bestand
$ echo 'goot tay!' > output.txt
Vervolgens sturen we de inhoud naar het stdin van tr:
 $ tr < output.txt t d good day! 
Zoals je kunt zien verliep alles zoals verwacht, en is er een leuk bericht op het scherm gedrukt.

Pijpleidingen

Met behulp van de pijpoperator | we kunnen meerdere commando's aan elkaar koppelen, zodat de stdout van het commando aan de linkerkant van de operator wordt doorgegeven aan de stdin van het commando er rechts van. We kunnen dit snel aantonen door de tr commando nogmaals:
 $ echo 'goot day!' | tr t d goede dag! 
Wat is er gebeurd? De standaarduitvoer van het echo-commando (bestaande uit de string 'goot tay!') Is achtergrondmuziek naar de standaardinvoer van de tr commando, dat de string vertaalt. Eindelijk zien we tr standaard output op scherm. Maar de pijp kan natuurlijk wel door. Stel je voor dat we alleen het woord 'goed' willen weergeven:
 $ echo 'goot tay!' | tr t d | cut -f 1 -d "
Wat we hier hebben gedaan, is het toevoegen van het besnoeiing commando naar de pijp, waarbij je de stdout van tr naar zijn stdin. De besnoeiing commando gebruikt de spatie als scheidingsteken (-d switch) en selecteert alleen het eerste veld, waarbij de string 'goed' wordt geretourneerd.

T-stuk gebruiken

De tee commando leest standaardinvoer en stuurt het tegelijkertijd door naar zowel standaarduitvoer als naar een bestand, waardoor het mogelijk wordt een 'T' in onze pipe te maken. Laten we het bovenstaande voorbeeld hergebruiken, en dit keer het tussenresultaat ('goede dag!') Ook naar het output.txt-bestand sturen:
$ echo 'goot tay!' | tr t d | tee ouput.txt | cut -f 1 -d "
De uitvoer op het scherm is hetzelfde als voorheen ('goed'), maar als we het bestand output.txt lezen, kunnen we zien dat de 'goede dag!' string is ernaar geschreven. Dit komt omdat 'goede dag!' was de standaard output die in de pijp stroomde toen we onze tee.
T-stuk is ook handig in enkele specifieke omstandigheden. Als u bijvoorbeeld iets probeert te 'echoën' naar een bestand waarvoor root-rechten nodig zijn om te worden geschreven, zult u merken dat de dingen niet gaan zoals verwacht:
 $ sudo echo "linuxconfig.org"> protected.txt -bash: protected.txt: toestemming geweigerd 
Wat is er gebeurd? Je had waarschijnlijk verwacht dat het commando succesvol zou zijn, omdat je het vooraf had gezet met sudo, maar het is hoe dan ook mislukt. Dit komt omdat u zojuist het echo commando met privileges, maar dat gaf je geen schrijfrechten voor het bestand. Laten we het in plaats daarvan op deze manier proberen:
$ echo "linuxconfig.org" | sudo tee protected.txt> / dev / null
Hier voeren we echo uit als een normale gebruiker, maar de omleiding zelf wordt uitgevoerd met root-privileges, dus deze keer slaagt het commando. We hebben ook een extra omleiding toegevoegd aan / dev / null, omdat we de uitvoer niet nodig hadden om op het scherm te worden weergegeven.
Merk op dat bij gebruik van deze techniek de uitvoer niet wordt toegevoegd aan het bestemmingsbestand: dit laatste wordt overschreven en de vorige inhoud gaat verloren. Om aan het bestand toe te voegen, moeten we de -een overschakelen naar tee (afkorting voor --append).
Pas op, een beetje afleiding hier kan vreselijke dingen veroorzaken!



Niemand heeft nog op dit artikel gereageerd.

Een verzameling nuttige informatie over het Linux-besturingssysteem en nieuwe technologieën
Nieuwe artikelen, praktische tips, gedetailleerde recensies en handleidingen. Voel je thuis in de wereld van het Linux-besturingssysteem