Hur man lägger till ett GUI till Linux Shell-skript

Du kan använda GUI-fönster, reglage, radioknappar, förloppsindikatorer och mer i dina Bash-skript. Lär dig hur du använder Zenity-verktygslådan och ge dina Bash-skript en ansiktslyftning. Vi visar dig hur.

Bash scripting är ett kraftfullt programmeringsspråk och eftersom det är inbyggt i Bash-skalet är det lätt tillgängligt för alla. Det är ett lätt språk att börja programmera på. Eftersom det är tolkat behöver du inte kompilera dina skript. Så snart du har redigerat skriptfilen och gjort den körbar kan du köra den. Detta gör kodnings-, körnings- och felsökningscykeln ganska effektiv.

Det finns två huvudsakliga klagomål människor har med Bash-skript, och det första är hastighet. Eftersom Bash-skalet tolkar kommandona i skriptet, körs de inte lika snabbt som kompilerad kod. Men detta är som att klaga på att en traktor inte är lika snabb som en bil; de är avsedda för olika saker.

Det finns dock två typer av hastighet. Du kan ofta slå ihop ett snabbt skript och använda det för att utföra en uppgift mycket snabbare än att utveckla en lösning i en kompilerade språk, som C.

Det andra klagomålet folk har med Bash-skript är användargränssnittet – det är ett terminalfönster. Visst, ibland spelar gränssnittet ingen roll. Om den enda personen som någonsin kommer att använda skriptet är dess författare, är gränssnittet förmodligen inte så viktigt. Det spelar heller ingen roll för skript som utför bakgrundsbearbetning och batchtyp. Vanligtvis behöver sådana skript inte mycket (om någon) användarinteraktion.

Det finns tillfällen när du behöver något lite mer intuitivt och modernt än terminalfönstret. De flesta känner till a grafiskt användargränssnitt (GUI). För att ge människor en upplevelse som är så friktionsfri som möjligt måste du skapa och använda GUI-element från dina skript.

Zenity-applikationen

zenity låter dig införliva ett brett utbud av grafiska gränssnittselement i dina Bash-skript. Dess en kraftfull verktygslåda som ger dina manus en modern känsla och ett modernt, välbekant utseende.

zenity är förinstallerat på Ubuntu, Fedora och Manjaro-distributioner. Det är en del av GNOME. Om du använder KDE kanske du vill kolla in kdialog istället, även om zenity körs på vilken skrivbordsmiljö som helst.

Exemplen i den här artikeln visar hur du skapar de olika dialogfönstren från kommandoraden, hur du fångar deras returvärden och användarval i variabler och hur du använder dialogfönstren i skript.

Vi avslutar med en liten applikation som använder alla tre typerna av dialogfönster.

Kalenderdialogfönstret

Ett kalenderdialogfönster låter någon välja ett datum. För att skapa en med zenity krävs ett enda kommando av två ord:

zenity --calendar

Kalenderdialogfönstret visas. Detta har alla funktioner du kan förvänta dig av en vanlig datumväljare. Du kan ändra månad och år och klicka på en dag för att välja det datumet. Som standard är dagens datum markerat när fönstret visas.

Klicka på ”OK” för att stänga dialogfönstret och välj det markerade datumet. Att dubbelklicka på ett datum gör samma sak.

Om du inte vill göra ett datumval, klicka på ”Avbryt”, tryck på ”Esc”-tangenten på ditt tangentbord eller stäng dialogrutan.

I exemplet ovan är 19 augusti 2019 vald. Om användaren klickar på ”OK”, stängs kalendern och det valda datumet skrivs ut i terminalfönstret.

Du kan ignorera raden ”GTKDialog mappad utan en övergående förälder. Detta är avskräckt.”

GTK står för GIMP verktygssats, som är verktygslådan som används för att utveckla GNOME gränssnitt. Det skapades ursprungligen av författarna till GNU Image Manipulation Program (GIMP). GNU står för GNU är inte Unix.

GTK-motorn varnar författarna av zenity att de har använt en GTK-komponent på ett icke-standardiserat sätt.

Fånga datumvärdet

Att skriva ut datumet till terminalen gör inte så mycket för oss. Om vi ​​ska anropa den här kalendern från ett av våra skript måste vi fånga det valda datumvärdet så att vi kan göra något användbart med det i vårt skript. Vi kommer också att anpassa kalendern något.

Vi använder följande alternativ med kalendern. De måste alla användas med den dubbelstreckade ”–”-flaggan:

–text: Anger en textsträng som ska visas i kalendern. Den ersätter standardinställningen ”Välj ett datum underifrån.”
–title: Ställer in titeln på kalenderdialogfönstret.
–dag: Ställer in den dag som väljs när kalendern öppnas.
–månad: Ställer in den månad som väljs när kalendern öppnas.
–år: Ställer in det år som väljs när kalendern öppnas.

Vi använder en variabel som heter ChosenDate för att fånga datumet som returneras från kalendern. Och vi använder echo $ChosenDate för att skriva ut det datumet till terminalfönstret.

Ja, vi uppnådde samma resultat i föregående exempel, men här har vi det valda datumet lagrat i en variabel. I det föregående exemplet var det utskrivet och glömt.

ChosenDate=$(zenity -- calendar --text "Choose a date" --title "How-To Geek Rota" --day 1 -- month 9 --year 2019); echo $ChosenDate

Nu visar kalendern vår prompt och vår fönstertitel. Datumet är satt till vårt valda startdatum snarare än dagens datum.

Vi kan också anpassa formatet för datumsträngen som returneras när ett val görs. Alternativet –date-format måste följas av en formatspecifikation. Detta är en sträng av tokens som definierar data och format som ska inkluderas i utdata. Tokens är samma som de som används med strftime() C språkfunktion och det finns ett stort urval av dem.

De tokens vi använder är:

%A: Veckodagens fullständiga namn.
%d: Dagen i månaden som en siffra.
%m: Månaden som en siffra.
%y: Årtalet som två siffror (inget århundrade).

ChosenDate=$(zenity -- calendar --text "Choose a date" --title "How-To Geek Rota" --date-format="%A %d/%m/%y" --day 1 -- month 9 --year 2019); echo $ChosenDate

Någon väljer ett datum:

Och datumet returneras med vårt format. Den visar namnet på veckodagen, följt av datumet i europeisk ordning: dag, månad, år.

Dialogfönstret för filval: Välja en fil

Dialogfönster för filval är ganska komplicerade. Människor kan bläddra igenom filsystemet, markera en eller flera filer och klicka sedan på ”OK” för att välja dessa filer eller avbryta valet helt.

zenity tillhandahåller all denna funktionalitet och mer. Och det är lika enkelt att använda som kalenderdialogfönstret.

De nya alternativen vi kommer att använda är:

–filval: Berättar för Zenity att vi vill använda ett filvalsdialogfönster.
–flera: Låter någon välja mer än en fil.
–fil-filter: Talar om för fildialogfönstret vilka filtyper som ska visas.

zenity --file-selection --tile "How-To Geek" --multiple --file-filter="*.mm *.png *.page *.sh *.txt"

Dialogfönstret för filval är lika funktionellt som alla andra filvalsfönster.

Användaren kan bläddra igenom filsystemet och välja önskad fil.

Vi har bläddrat till en ny katalog och valt en fil som heter ”button_hybrid.png.”

När du klickar på ”OK” stängs dialogrutan för filval och filnamnet och sökvägen skrivs ut i terminalfönstret.

Om du behöver använda filnamnet i någon vidare bearbetning kan du fånga det i en variabel, precis som du gjorde för datumet från kalendern.

Dialogfönstret Filval: Spara en fil

Om vi ​​lägger till ett alternativ kan vi förvandla filvalsdialogfönstret till ett filsparningsdialogfönster. Alternativet är –spara. Vi kommer också att använda alternativet –confirm-overwrite. Detta uppmanar personen att bekräfta att han vill skriva över en befintlig fil.

Response=$(zenity --file-selection --save --confirm-overwrite); echo $Response

Dialogrutan för att spara filer visas. Observera att det finns ett textfält där någon kan skriva ett filnamn.

Användaren kan bläddra till önskad plats i filsystemet, ange ett namn för filen eller klicka på en befintlig fil för att skriva över den.

I exemplet ovan markerade användaren en befintlig fil.

När han klickar på ”OK” visas ett bekräftelsefönster som ber honom att bekräfta att han vill ersätta den befintliga filen. Observera att namnet på filen visas i varningsdialogrutan. Det är den sortens uppmärksamhet på detaljer som ger zenity dess professionella utseende.

Om vi ​​inte hade använt alternativet –confirm-overwrite, skulle filen tyst ha skrivits över.

Namnet på filen lagras i variabeln Response, som skrivs ut till terminalfönstret.

Meddelandedialog Windows

Med zenity är det enkelt att inkludera smarta meddelandedialogfönster i dina skript. Det finns lagerdialogfönster som du kan ringa till för att ge information, varningar, felmeddelanden och frågor till användaren.

För att skapa ett felmeddelandedialogfönster, använd följande kommando:

zenity --error --width 300 --text "Permission denied. Cannot write to the file."

De nya alternativen vi använder är:

–error: Berättar för Zenity att vi vill använda ett feldialogfönster.
–bredd: Ställer in fönstrets initiala bredd.

Feldialogfönstret visas med den angivna bredden. Den använder standard GTK-felikonen.

För att skapa ett informationsdialogfönster, använd följande kommando:

zenity --info --width 300 --text "Update complete. Click OK to continue."

Det nya alternativet vi använder är –info , som säger till Zenity att skapa ett informationsdialogfönster.

För att skapa ett frågedialogfönster, använd följande kommando:

zenity --question --width 300 --text "Are you happy to proceed?"; echo $?

Det nya alternativet vi använder är –question, som säger till Zenity att skapa ett frågedialogfönster.

$? är en speciell parameter. Den innehåller returvärdet från den senast exekverade pipeline i förgrunden. Generellt sett är detta värdet från den senast avslutade processen. Ett nollvärde betyder ”OK” och ett värde på ett eller flera betyder ”Avbryt”.

Detta är en allmän teknik som du kan tillämpa på vilket som helst av Zenity-dialogfönsterna. Genom att kontrollera detta värde i ditt skript kan du avgöra om data som returneras från ett dialogfönster ska bearbetas eller ignoreras.

Vi klickade på ”Ja”, så returkoden är en nolla som indikerar ”OK”.

För att skapa ett varningsdialogfönster, använd följande kommando:

zenity --warning --title "Low Hard Drive Space" --width 300 --text "There may not be enough hard drive space to save the backup."

Det nya alternativet vi använder är –warning , som säger till Zenity att skapa ett varningsdialogfönster.

Varningsdialogfönstret visas. Det är inte en fråga, så den har bara en knapp.

Framstegsdialogfönstret

Du kan använda zenitys framstegsdialogfönster för att visa en förloppsindikator som visar hur nära att ditt skript är färdigt.

Förloppsindikatorn avanceras enligt de värden som skickas in i den från ditt skript. För att demonstrera principen, använd följande kommando:

(for i in $(seq 0 10 100); do echo $i; sleep 1; done)

Kommandot delas upp så här:

Kommandot seq stegar genom en sekvens från 0 till 100, i steg om 10.
Vid varje steg lagras värdet i variabeln i. Detta skrivs ut till terminalfönstret.
Kommandot pausas i en sekund på grund av kommandot sleep 1.

Vi kan använda detta med zenitys framstegsdialogfönster för att visa förloppsindikatorn. Observera att vi överför resultatet från det föregående kommandot till zenity:

(for i in $(seq 0 10 100); do echo $i; sleep 1; done) | zenity --progress --title "How-To Geek" -- auto-close

De nya alternativen vi använder är:

–progress: Berättar för Zenity att vi vill använda ett framstegsdialogfönster.
–autostäng: Stänger dialogrutan när förloppsindikatorn når 100 procent.

Fönstret för förloppsdialogen visas och stapeln flyttas mot 100 procent och pausar en sekund mellan varje steg.

Vi kan använda konceptet med att föra in värden till zenity för att inkludera förloppsdialogfönstret i ett skript.

Skriv in den här texten i en editor och spara den som ”progress.sh.”

!/bin/bash

function work-list () {

echo "# First work item" 
echo "25"
sleep 1

echo "# Second work item" 
echo "50"
sleep 1

echo "# Third work item" 
echo "75"
sleep 1

echo "# Last work item" 
echo "100"
sleep 1

}

work-list | zenity --progress --title "How-To Geek" --auto-close

exit 0

Här är en sammanfattning av manuset:

Skriptet definierar en funktion som kallas work-list. Det är här du lägger dina kommandon och instruktioner för att utföra riktigt arbete. Byt ut vart och ett av sömn 1-kommandona med dina riktiga.
zenity accepterar ekot ”# …”-linjer och visar dem i förloppsdialogfönstret. Ändra texten på dessa rader så att de skickar informativa meddelanden till användaren.
Ekolinjerna som innehåller siffror, såsom eko ​​”25″ , accepteras också av zenity och ställer in värdet på förloppsindikatorn.
Work-list-funktionen anropas och överförs till zenity.

Använd det här kommandot för att göra skriptet körbart:

chmod +x progress.sh

Använd detta kommando för att köra skriptet:

./progress.sh

Skriptet körs och textmeddelandet ändras när varje fas av skriptet körs. Förloppsindikatorn flyttas i steg mot 100 procent.

Dialogfönstret Skala

Skalningsdialogfönstret låter någon flytta ett skjutreglage för att välja ett numeriskt värde. Det betyder att hon inte kan ange ett värde som är för högt eller lågt.

De nya alternativen vi använder är:

–scale: Berättar för Zenity att vi vill använda ett skalningsdialogfönster.
–min-värde: Ställer in det lägsta värdet för skalan.
–max-värde: Ställer in maxvärdet för skalan.
–steg: Ställer in hur mycket skjutreglaget flyttas in när piltangenterna används. Detta påverkar inte skjutreglagets rörelser om någon använder musen.
–värde: Ställer in startvärdet och positionen för reglaget.

Detta är kommandot vi använder:

Response=$(zenity --scale --title "How-To Geek" --text "Select magnification." --min-value=0 --max-value=30 --step=3 --value15); echo $Response

Skjutreglagets dialogfönster visas med skjutreglaget inställt på 15.

Användaren kan flytta reglaget för att välja ett nytt värde.

När hon klickar på ”OK” överförs värdet till variabeln Response och skrivs ut till terminalfönstret.

Inmatningsdialogfönstret

Inmatningsdialogfönstret låter någon mata in text.

De nya alternativen vi använder är:

–entry: Berättar för Zenity att vi vill använda ett inmatningsdialogfönster.
–entry-text: Du kan använda detta om du vill skriva ett föreslaget värde i textinmatningsfältet. Vi använder ”” för att tvinga fram ett tomt fält. Detta är inte strikt nödvändigt, men vi ville dokumentera alternativet.

Det fullständiga kommandot ser ut så här:

Response=$(zenity --entry --text "Enter your search term" --title "Howe-To Geek" --entry-text=""); echo $Response

Ett enkelt dialogfönster visas med ett textinmatningsfält.

Någon kan skriva och redigera text.

När han klickar på ”OK” tilldelas värdet han skrev till variabeln Response. Vi använder eko för att skriva ut variabelns värde i terminalfönstret.

Få alltid att falla på plats

Låt oss sätta ihop dessa tekniker och skapa ett funktionellt manus. Skriptet kommer att utföra en hårdvaruinformationsskanning och presentera resultaten för användaren i ett rullande textfönster. Hon kan välja en lång eller kort skanningstyp.

För det här skriptet kommer vi att använda tre typer av dialogfönster, varav två är nya för oss:

Det första är ett listdialogfönster. Det låter någon göra ett val.
Det andra är ett förloppsdialogfönster som låter användaren veta att något händer, och hon bör vänta.
Det tredje är ett textinformationsfönster som visar resultaten för användaren.

Skriv in den här texten i en editor och spara den som ”hardware-info.sh.”

#!/bin/bash

# Display hardware listing for this computer

TempFile=$(mktemp)

ListType=`zenity --width=400 --height=275 --list --radiolist 
     --title 'Hardware Scan' 
     --text 'Select the scan type:' 
     --column 'Select' 
     --column 'Scan Type' TRUE "Short" FALSE "Long"`

if [[ $? -eq 1 ]]; then

  # they pressed Cancel or closed the dialog window 
  zenity --error --title="Scan Declined" --width=200 
       --text="Hardware scan skipped"
  exit 1
 
elif [ $ListType == "Short" ]; then

  # they selected the short radio button 
  Flag="--short"
 
else

  # they selected the long radio button 
  Flag="" 
fi

# search for hardware info with the appropriate value in $Flag
hwinfo $Flag | tee >(zenity --width=200 --height=100 
     --title="Collating Information" --progress 
     --pulsate --text="Checking hardware..." 
     --auto-kill --auto-close) >${TempFile}
 
# Display the hardware info in a scrolling window
zenity --width=800 --height=600 
     --title "Hardware Details" 
     --text-info --filename="${TempFile}"
 
exit 0

Använd detta kommando för att göra det körbart:

chmod +x hardware-info.sh

Det här skriptet skapar en temporär fil, och namnet på filen hålls i TempFile-variabeln:

TempFile=$(mktemp)

Skriptet använder alternativet –list för att skapa ett zenity-dialogfönster som kallas ett listdialogfönster. Tecknen ”” i slutet av raderna säger åt manuset att behandla dem som en lång rad som är lindad runt. Här är processen:

Vi anger en bredd och höjd för fönstret.
Listdialogfönstret stöder kolumner. Alternativet –radiolist gör att den första kolumnen blir en kolumn med radioknappar.
Vi ställer in en titel- och textprompt för fönstret.
Vi ställer in titeln på den första kolumnen till ”Välj”. Innehållet i denna kolumn kommer att vara radioknapparna.
Vi ställer in titeln på den andra kolumnen till ”Välj”, och vi tillhandahåller innehållet i den andra kolumnen. Den här kolumnen innehåller två textetiketter: ”Kort” och ”Lång”. Indikatorerna TRUE och FALSE betyder att alternativet ”Kort” är valt som standard när dialogfönstret visas.
Vi lagrar resultatet från detta dialogfönster i en variabel som heter ListType.

ListType=`zenity --width=400 --height=275 --list --radiolist  
     --title 'Hardware Scan'  
     --text 'Select the scan type:'  
     --column 'Select'  
     --column 'Scan Type' TRUE "Short" FALSE "Long"`

Om användaren trycker på ”Avbryt”, behöver vi inte kontrollera värdet i ListType, vi kan helt enkelt avsluta. Om han trycker på ”OK” måste vi ta reda på om han valde alternativknappen ”Kort” eller ”Lång”:

Den speciella parametern $? är lika med noll om användaren tryckte på ”OK”. Det är lika med ett om han tryckte på ”Avbryt” eller stängde fönstret.
Om det är lika med ett, visar skriptet ett fönster för felinformation och avslutas. Om han trycker på ”OK” går vi vidare för att testa värdet i ListType-variabeln.
Om ListType-variabeln har värdet ”Short”, ställer skriptet en variabel som heter Flag till lika med ”–short”.
Om ListType-variabeln inte har värdet ”Short” måste den hålla värdet ”Long”. Skriptet ställer in en variabel som heter Flagga till lika med ””, vilket är en tom sträng.
Skriptet använder variabeln Flagga i nästa avsnitt.

if [[ $? -eq 1 ]]; then 

  # they pressed Cancel or closed the dialog window 
  zenity --error --title="Scan Declined" --width=200  --text="Hardware scan skipped" 
  exit 1 

elif [ $ListType == "Short" ]; then 

 # they selected the short radio button 
 Flag="--short" 

else 

 # they selected the long radio button 
 Flag="" 
fi

Nu när skriptet vet vilken typ av skanning användaren vill ha kan vi utföra skanningen av hårdvaruinformation:

Skriptet anropar kommandot hwinfo och skickar det till värdet i Flag-variabeln.
Om Flaggan innehåller ”–short”, utför hwinfo-kommandot en kort skanning. Om värdet för Flagga är ””, överförs ingenting till hwinfo och en standard, lång skanning utförs.
Skriptet skickar utdata från hwinfo till tee. tee skickar utdata till Zenity och TempFile.
Skriptet skapar ett dialogfönster för förloppsindikatorn. Den ställer in bredden och höjden på dialogfönstret, samt rubrik och prompttexter.
Skriptet kan inte i förväg veta hur mycket information hwinfo-kommandot kommer att producera, så det kan inte ställa in förloppsindikatorn för att avancera korrekt till 100 procent. Alternativet –pulsate gör att förloppsdialogrutan visar en rörlig indikator. Detta informerar användaren om att något händer och han bör vänta.
Alternativet –auto-kill avslutar skriptet om någon klickar på ”Avbryt”.
Alternativet –auto-stäng gör att förloppsdialogrutan stängs automatiskt när processen som den övervakar slutförs.

# search for hardware info with the appropriate value in $Flag
hwinfo $Flag | tee >(zenity --width=200 --height=100 
     --title="Collating Information" --progress 
     --pulsate --text="Checking hardware..." 
     --auto-kill --auto-close) >${TempFile}

När hwinfo-skanningen är klar anropar skriptet zenity för att skapa ett textinformationsdialogfönster med alternativet –text-info. Textinformationsdialogrutan visar innehållet i TempFile-filen:

Skriptet ställer in bredden och höjden på dialogfönstret och titeltexten.
Alternativet –flename används för att läsa innehållet i filen som finns i TempFIle-variabeln.

# Display the hardware info in a scrolling window 
zenity --width=800 --height=600  
     --title "Hardware Details"  
     --text-info --filename="${TempFile}"

När användaren stänger textinformationsdialogrutan avslutas skriptet.

exit 0

Låt oss tända den och ta en titt.

./hardware-info.sh

Listrutan visas. Alternativet ”Kort” är valt som standard.

Lista dialogrutan med

Låt oss välja ”Lång” och klicka sedan på ”OK”.

Lista dialogrutan med

Förloppsfönstret visas med en glidande indikator. Den finns kvar på skärmen tills hårdvaruskanningen är klar.

När hårdvaruskanningen är klar visas dialogrutan med textinformation med detaljer från skanningen.

Klicka på ”OK”.

Även en inbiten kommandoradsjockey måste erkänna att ett par GUI-dialogfönster kan ge ett ödmjukt Bash-skript en professionell touch.