Hoppa till innehåll

Linux-kommandon

Den här sidan ger en introduktion till Linux och de kommandon du behöver för att hantera en server. Den går inte igenom varje kommando med alla flaggor, utan innehåller:

  • skalet och hur du arbetar effektivt i terminalen
  • filsystemet och var saker finns på en server
  • en lista med kommandon du ska kunna hantera
  • användare och rättigheter
  • in- och utdata, omdirigering och pipes
  • processer, portar och miljövariabler
  • en introduktion till Bash-skript
  • övningar att göra på egen hand

Allt här använder du senare i kursen: när du gör i ordning din Cumulus-server, läser loggar, felsöker en app som inte startar och skriver Dockerfiler.

Tidsåtgång: Ungefär 30–40 minuter att läsa och en och en halv timme för övningarna. Extraövningarna tar ungefär lika lång tid till.

Gå först igenom Docker-kommandon. Allt på den här sidan prövar du sedan i en Ubuntu-container, utan risk att förstöra något. Skapa containern med ett namn, så att du kan fortsätta där du slutade:

Terminal window
# Första gången
docker run -it --name linux ubuntu:26.04
# Nästa gång
docker start -i linux

Ubuntu-imagen för Docker är minimal. Den saknar bland annat textredigerare och man-sidor, som du installerar i övningarna. I containern är du inloggad som root, och sudo finns inte. Skriv därför kommandona utan sudo. På din server är du en vanlig användare och skriver sudo framför de kommandon som kräver administratörsrättigheter.

Skalet (shell) är programmet som tolkar det du skriver i terminalen och kör kommandona. Det vanligaste skalet i Linux är bash (Bourne-Again Shell). macOS använder zsh, som liknar bash. Allt på den här sidan fungerar i båda.

Ett kommando består av ett programnamn, flaggor och argument:

Terminal window
ls -l -a /etc
# ^ ^^^^^ ^^^^
# | | argument: vad kommandot ska arbeta med
# | flaggor: hur det ska göra det, ofta ihopskrivna som -la
# programmet

Några tangenter sparar mycket tid:

Tangent Vad den gör
Tab Kompletterar kommandon och sökvägar. Tryck två gånger för att se alternativen.
Pil upp och ned Bläddrar i tidigare kommandon
Ctrl+R Söker bakåt i historiken
Ctrl+C Avbryter det kommando som körs
Ctrl+D Avslutar skalet, samma sak som exit
Ctrl+A och Ctrl+E Hoppar till början och slutet av raden
Ctrl+L Rensar skärmen, samma sak som clear

Behöver du veta hur ett kommando fungerar skriver du <kommando> --help för en kort sammanfattning, eller man <kommando> för hela manualen. Du lämnar manualen med q. Man-sidorna finns också på manpages.ubuntu.com. tldr visar korta exempel i stället för hela manualen, och explainshell förklarar varje del av ett kommando du har hittat någonstans.

På en server redigerar du filer direkt i terminalen. nano är enklast: kommandona står längst ned på skärmen, där ^ betyder Ctrl. Ctrl+O sparar och Ctrl+X avslutar. vim finns på nästan alla servrar och är mycket kraftfullt, men fungerar annorlunda. När vim startar är tangenterna kommandon, och du kan skriva text först efter att ha tryckt i. Esc tar dig tillbaka. Hamnar du i vim av misstag trycker du Esc och skriver :q! för att avsluta utan att spara.

Allt i Linux ligger i ett enda träd som börjar i roten, /. Det finns inga enhetsbokstäver som C:. Katalogerna har bestämda uppgifter:

Katalog Innehåll
/etc Konfigurationsfiler, till exempel /etc/ssh/sshd_config
/home Användarnas hemkataloger, till exempel /home/student
/root Hemkatalogen för root
/var/log Loggfiler
/srv Data som servern tillhandahåller, till exempel webbapplikationer
/tmp Tillfälliga filer, som töms vid omstart
/usr/bin Program
/proc Information om processer och systemet, skapad av kärnan medan systemet körs

En absolut sökväg börjar i roten: /var/log/dpkg.log. En relativ sökväg utgår från den katalog du står i: log/dpkg.log. Några förkortningar:

Förkortning Betyder
~ Din hemkatalog
. Den katalog du står i
.. Katalogen ovanför
- Den katalog du var i senast, i cd -

Filer och kataloger vars namn börjar med punkt, som .bashrc, är dolda och visas bara med ls -a.

Kommando Vad det gör
pwd Visar vilken katalog du står i
ls -la Listar alla filer, även dolda, med rättigheter, ägare och storlek
cd <katalog> Byter katalog. Utan argument går du till hemkatalogen.
mkdir -p a/b/c Skapar kataloger, även de som saknas på vägen
touch <fil> Skapar en tom fil, eller uppdaterar tidsstämpeln på en befintlig
cp <från> <till> Kopierar. -r kopierar kataloger med innehåll.
mv <från> <till> Flyttar eller byter namn
rm <fil> Tar bort. -r tar bort kataloger med innehåll. Det finns ingen papperskorg.
ln -s <mål> <länk> Skapar en symbolisk länk
Kommando Vad det gör
cat <fil> Skriver ut en fil
less <fil> Visar en fil sida för sida. / söker och q avslutar.
head -n 20 <fil> Visar de första raderna
tail -n 20 <fil> Visar de sista raderna. -f följer filen medan den växer, som en logg.
grep <mönster> <fil> Visar rader som innehåller mönstret. -i ignorerar skiftläge, -r söker i kataloger.
find <katalog> -name '<mönster>' Letar efter filer
wc -l <fil> Räknar rader

På Ubuntu installeras program med apt, som hämtar paket från Ubuntus paketförråd.

Kommando Vad det gör
apt update Hämtar nya paketlistor. Kör det innan du installerar något.
apt upgrade Installerar nyare versioner av de paket som redan finns
apt install <paket> Installerar ett paket
apt remove <paket> Tar bort ett paket
apt search <ord> Söker efter paket
Kommando Vad det gör
whoami och id Visar vem du är och vilka grupper du tillhör
sudo <kommando> Kör ett kommando som root
adduser <namn> Skapar en användare med hemkatalog
addgroup <namn> Skapar en grupp
usermod -aG <grupp> <användare> Lägger till en användare i en grupp. Glöm inte -a.
su - <användare> Byter till en annan användare
chmod <rättigheter> <fil> Ändrar rättigheter
chown <användare>:<grupp> <fil> Ändrar ägare och grupp
Kommando Vad det gör
ps aux Listar alla processer
top Visar processerna live, sorterade efter CPU. q avslutar.
kill <pid> Ber en process att avslutas. kill -9 tvingar den.
ss -ltnp Visar vilka processer som lyssnar på vilka TCP-portar
curl <url> Hämtar en URL. -I visar bara svarets headers.
ssh <användare>@<värd> Loggar in på en annan dator
scp <från> <till> Kopierar filer över SSH
tar -czf <arkiv>.tar.gz <kataloger> Skapar ett komprimerat arkiv. -xzf packar upp och -tzf listar.
df -h Visar ledigt diskutrymme
du -sh <katalog> Visar hur mycket plats en katalog tar

Varje fil och katalog har en ägare, en grupp och rättigheter för tre kategorier: ägaren (u), gruppen (g) och övriga (o). ls -l visar dem:

-rw-r----- 1 deploy webapps 80 Nov 2 08:15 .env
^^^^^^^^^ ^^^^^^ ^^^^^^^
| | | ägare grupp
| | övriga: inga rättigheter
| gruppen: läsa
ägaren: läsa och skriva
Rättighet På en fil På en katalog
r (4) Läsa innehållet Lista filerna
w (2) Ändra innehållet Skapa och ta bort filer i den
x (1) Köra filen som ett program Gå in i katalogen

Rättigheterna skrivs ofta som tre siffror, en per kategori, där varje siffra är summan av de rättigheter som ska gälla. 640 betyder att ägaren får läsa och skriva (4+2), gruppen får läsa (4) och övriga ingenting. Några vanliga värden:

Värde Används till
755 Program, skript och kataloger som alla får läsa
644 Vanliga filer som alla får läsa
700 Kataloger bara du ska komma åt, som ~/.ssh
600 Hemligheter, som en .env-fil eller en privat SSH-nyckel

chmod förstår också bokstäver: chmod +x skript.sh gör en fil körbar, och chmod g+w katalog ger gruppen skrivrätt.

En fjärde siffra först sätter särskilda rättigheter. Den vanligaste är setgid (2) på en katalog, till exempel 2775. Då får nya filer i katalogen katalogens grupp i stället för skaparens, vilket gör det enkelt för flera användare att dela en katalog.

Varje program har tre standardströmmar: stdin (0) där det läser indata, stdout (1) dit det skriver sitt resultat, och stderr (2) dit det skriver felmeddelanden. Normalt är stdin tangentbordet och stdout och stderr terminalen, men du kan styra om dem:

Operator Vad den gör
> Skriver stdout till en fil, som skrivs över
>> Lägger till stdout sist i en fil
2> Skriver stderr till en fil
2>/dev/null Kastar felmeddelandena
&> Skriver både stdout och stderr till en fil
< Läser stdin från en fil
| En pipe: skickar stdout från ett kommando till stdin för nästa

Med pipes kan du bygga ihop små program som gör en sak var. Det är så du oftast söker i loggar:

Terminal window
# De fem vanligaste IP-adresserna i en webbservers logg
awk '{ print $1 }' access.log | sort | uniq -c | sort -rn | head -n 5

awk '{ print $1 }' skriver ut första fältet på varje rad, sort sorterar, uniq -c räknar likadana rader som ligger efter varandra, sort -rn sorterar numeriskt med störst först och head -n 5 behåller de fem första.

Miljövariabler är namngivna värden som ett program ärver från skalet som startar det. Så får din Node-applikation sin konfiguration, till exempel process.env.PORT.

Terminal window
echo $HOME # visar en variabel
GREETING=hej # sätter en variabel i skalet
export GREETING # gör den synlig för program som startas härifrån
PORT=8080 node app.js # sätter en variabel bara för ett kommando
env # listar alla exporterade variabler

PATH innehåller de kataloger där skalet letar efter program. Därför räcker det att skriva ls i stället för /usr/bin/ls.

På en riktig server startas tjänster som SSH-servern av systemd. Containern har ingen systemd, så kommandona nedan fungerar bara på din server:

Kommando Vad det gör
systemctl status <tjänst> Visar om tjänsten körs och de senaste loggraderna
sudo systemctl restart <tjänst> Startar om tjänsten
sudo systemctl enable <tjänst> Startar tjänsten automatiskt när servern startar
journalctl -u <tjänst> -f Följer tjänstens logg

Ett Bash-skript är en textfil med kommandon, som körs uppifrån och ned. Du kan redan programmera, så det nya är mest syntaxen:

#!/bin/bash
# Greets everyone given as arguments, or the world if none are given.
set -euo pipefail
if (($# == 0)); then
echo "Hej, världen!"
exit 0
fi
for name in "$@"; do
echo "Hej, $name!"
done
  • Första raden, shebang, anger vilket program som ska tolka filen.
  • set -euo pipefail gör skriptet säkrare: det avbryts vid första fel (-e), vid variabler som inte har något värde (-u) och när ett kommando mitt i en pipe misslyckas (-o pipefail).
  • $1, $2 och så vidare är argumenten, $# är antalet och "$@" är alla.
  • Skriv alltid variabler inom citattecken, "$name", så att värden med mellanslag inte delas upp.
  • [[ -d $katalog ]] testar om en katalog finns, [[ -f $fil ]] om en fil finns och [[ -z $text ]] om en sträng är tom.
  • Varje kommando lämnar en returkod: 0 betyder att det gick bra, allt annat betyder fel. $? innehåller den senaste. Avsluta ett skript med exit 1 när något går fel.
  • Skriv felmeddelanden till stderr med >&2, så att stdout bara innehåller resultatet.

Gör skriptet körbart och kör det:

Terminal window
chmod +x hello.sh
./hello.sh Ada Grace

Använd ShellCheck på dina skript. Det hittar de vanligaste felen och förklarar varför de är fel.

Tidsåtgång: Ungefär en och en halv timme för de tio övningarna.

När du har gått igenom sidan kan du pröva dina kunskaper med övningarna nedan. Gör dem i ordning i din Ubuntu-container. Försök själv innan du tittar på lösningsförslaget.

Tidsåtgång: Ungefär 5 minuter.

Ta reda på vilken katalog du står i, vem du är och vilken version av Ubuntu containern kör. Lista sedan innehållet i roten, /, med rättigheter och dolda filer.

Terminal window
pwd
whoami
cat /etc/os-release
ls -la /

Tidsåtgång: Ungefär 5 minuter.

Uppdatera paketlistorna och installera paketen nano, less, curl, iproute2, netcat-openbsd och adduser. Du behöver dem i övningarna nedan.

Terminal window
apt update
apt install nano less curl iproute2 netcat-openbsd adduser

Man-sidorna saknas i den minimala imagen. Vill du läsa dem i containern kör du unminimize (installera det först med apt install unminimize om det saknas).

Tidsåtgång: Ungefär 10 minuter.

Skapa katalogerna ~/projekt/app/src och ~/projekt/app/logs med ett kommando. Skapa filen ~/projekt/app/src/server.js och skriv en rad JavaScript i den med nano. Lista sedan hela trädet under ~/projekt.

Terminal window
mkdir -p ~/projekt/app/src ~/projekt/app/logs
nano ~/projekt/app/src/server.js
ls -R ~/projekt

mkdir -p skapar också de kataloger som saknas på vägen, och klagar inte om katalogen redan finns.

Tidsåtgång: Ungefär 5 minuter.

Skriv raden start till filen ~/projekt/app/logs/app.log utan att öppna någon textredigerare. Lägg sedan till raden stopp sist i filen och visa innehållet. Vad händer om du använder > i stället för >> på andra raden?

Terminal window
echo start > ~/projekt/app/logs/app.log
echo stopp >> ~/projekt/app/logs/app.log
cat ~/projekt/app/logs/app.log

Med > skrivs filen över, och bara stopp blir kvar.

Tidsåtgång: Ungefär 5 minuter.

Kopiera hela katalogen ~/projekt/app till ~/projekt/app-backup. Byt namn på ~/projekt/app-backup till ~/projekt/app-gammal. Ta sedan bort ~/projekt/app-gammal.

Terminal window
cp -r ~/projekt/app ~/projekt/app-backup
mv ~/projekt/app-backup ~/projekt/app-gammal
rm -r ~/projekt/app-gammal

rm -r frågar inte och har ingen papperskorg. Kontrollera sökvägen innan du trycker Enter.

Tidsåtgång: Ungefär 10 minuter.

Skapa filen ~/projekt/app/.env med raden SECRET=hemligt. Ge den rättigheterna 600 och kontrollera resultatet med ls -l. Vad betyder -rw-------? Vilka rättigheter har /tmp, och vad betyder t i slutet?

Terminal window
echo 'SECRET=hemligt' > ~/projekt/app/.env
chmod 600 ~/projekt/app/.env
ls -l ~/projekt/app/.env
ls -ld /tmp

-rw------- betyder att det är en vanlig fil (-), att ägaren får läsa och skriva och att gruppen och övriga inte får någonting. /tmp har drwxrwxrwt: alla får skapa filer där, men t, sticky bit, gör att man bara får ta bort sina egna.

Tidsåtgång: Ungefär 15 minuter.

apt loggar allt det installerar i /var/log/dpkg.log. Hur många paket har installerats? Vilka fem paket installerades sist? Använd grep, wc, tail och awk.

Terminal window
grep ' install ' /var/log/dpkg.log | wc -l
grep ' install ' /var/log/dpkg.log | tail -n 5 | awk '{ print $4 }'

Mellanslagen i ' install ' gör att bara raderna där install är ett eget ord kommer med, och inte till exempel status installed.

Tidsåtgång: Ungefär 10 minuter.

Starta nc -lk 8080 &, som lyssnar på port 8080. Ta reda på vilken process som lyssnar på porten och avsluta den. Tänk dig att din Node-app inte startar och säger EADDRINUSE. Vad gör du då?

Terminal window
nc -lk 8080 &
ss -ltnp
# LISTEN 0 1 0.0.0.0:8080 0.0.0.0:* users:(("nc",pid=123,fd=3))
kill 123

EADDRINUSE betyder att porten redan används. Med ss -ltnp ser du av vilken process, och bestämmer sedan om den ska avslutas eller om din app ska använda en annan port. På en server behöver du sudo för att se processer som andra användare äger.

Tidsåtgång: Ungefär 10 minuter.

Sätt variabeln GREETING till hej i skalet och kör bash -c 'echo $GREETING'. Varför skrivs ingenting ut? Gör om det med export. Kör sedan samma kommando med variabeln satt bara för det kommandot.

Terminal window
GREETING=hej
bash -c 'echo $GREETING' # tomt: variabeln finns bara i ditt skal
export GREETING
bash -c 'echo $GREETING' # hej
GREETING=hallå bash -c 'echo $GREETING' # hallå, bara för det här kommandot

bash -c startar ett nytt skal, som bara ärver exporterade variabler. På samma sätt får en Node-app bara de variabler som finns i miljön när den startar.

Tidsåtgång: Ungefär 15 minuter.

Skriv skriptet hello.sh från avsnittet om Bash-skript, gör det körbart och kör det utan argument, med två namn och med "Ada Lovelace". Vad händer om du tar bort citattecknen kring "$@"?

Terminal window
nano hello.sh
chmod +x hello.sh
./hello.sh
./hello.sh Ada Grace
./hello.sh "Ada Lovelace"

Med citattecknen skrivs Hej, Ada Lovelace! ut. Tar du bort dem runt "$@" delas namnet upp i två argument, och skriptet hälsar på Ada och Lovelace var för sig.

Tidsåtgång: Ungefär en och en halv timme för alla sju.

Övningarna ovan täcker det du behöver för resten av kursen. Har du tid och vill öva mer fortsätter du här, i samma container.

Tidsåtgång: Ungefär 10 minuter.

Hur många filer som slutar på .conf finns det under /etc? Var ligger filen ubuntu.sources, som talar om varifrån apt hämtar paket?

Terminal window
find /etc -name '*.conf' | wc -l
find / -name 'ubuntu.sources' 2>/dev/null

Den ligger i /etc/apt/sources.list.d/. 2>/dev/null kastar felmeddelandena om kataloger som inte går att läsa, som annars kan fylla skärmen när du söker från roten.

Tidsåtgång: Ungefär 15 minuter.

Skapa användarna ada och grace och gruppen devs, och lägg till båda användarna i gruppen. Skapa katalogen /srv/docs som ägs av root och gruppen devs, med rättigheterna 2770. Byt till ada och skapa en fil i katalogen. Vilken grupp får filen? Kan grace ändra den?

Terminal window
adduser --disabled-password --comment '' ada
adduser --disabled-password --comment '' grace
addgroup devs
usermod -aG devs ada
usermod -aG devs grace
mkdir /srv/docs
chown root:devs /srv/docs
chmod 2770 /srv/docs
su - ada
touch /srv/docs/anteckningar.txt
ls -l /srv/docs
exit

Filen får gruppen devs tack vare setgid-biten (2). Utan den hade den fått gruppen ada. Rättigheterna blir -rw-rw-r--, så grace kan ändra den. Rättigheterna för nya filer styrs av umask. Vanliga användare på Ubuntu har umask 0002 (kör umask och se), som ger gruppen skrivrätt. Setgid och en gemensam grupp räcker därför för att flera användare ska kunna dela en katalog.

Tidsåtgång: Ungefär 5 minuter.

Kör ls /etc /finns-inte. Skicka sedan resultatet till ut.txt och felmeddelandet till fel.txt. Kör kommandot en gång till och kasta felmeddelandet helt.

Terminal window
ls /etc /finns-inte
ls /etc /finns-inte > ut.txt 2> fel.txt
cat fel.txt
ls /etc /finns-inte 2>/dev/null

Tidsåtgång: Ungefär 5 minuter.

Starta sleep 600 i bakgrunden genom att avsluta kommandot med &. Hitta processens id med ps och avsluta den med kill. Kontrollera att den är borta.

Terminal window
sleep 600 &
ps aux | grep sleep
kill <pid>
ps aux | grep sleep

grep sleep hittar sig själv också, så en rad med grep sleep blir alltid kvar. pgrep sleep skriver bara ut id:t, och pkill sleep avslutar alla processer med det namnet.

Tidsåtgång: Ungefär 5 minuter.

Hämta bara svarets headers från https://coursepress.lnu.se. Vilken statuskod får du? Hämta sedan statuskoden ensam, utan något annat.

Terminal window
curl -I https://coursepress.lnu.se
curl -s -o /dev/null -w '%{http_code}\n' https://coursepress.lnu.se

-s tar bort förloppsmätaren, -o /dev/null kastar själva sidan och -w skriver ut det du ber om. Kombinationen är användbar i skript som kontrollerar att en webbplats svarar.

Tidsåtgång: Ungefär 10 minuter.

Skapa ett komprimerat arkiv av ~/projekt som heter projekt.tar.gz och lista innehållet utan att packa upp det. Hur mycket ledigt diskutrymme finns det, och vilka tre kataloger under /usr tar mest plats?

Terminal window
tar -czf ~/projekt.tar.gz -C ~ projekt
tar -tzf ~/projekt.tar.gz
df -h
du -sh /usr/* | sort -h | tail -n 3

-C ~ gör att sökvägarna i arkivet börjar på projekt/ i stället för /root/projekt/. sort -h sorterar storlekar som 12K och 3.4M rätt.

Tidsåtgång: Ungefär 30 minuter.

Skriv skriptet check-sites.sh som tar en eller flera URL:er som argument och skriver ut OK eller FEL följt av statuskoden för var och en. Utan argument ska skriptet skriva en hjälptext till stderr och avslutas med returkoden 1. Om någon webbplats inte svarar med 200 ska skriptet avslutas med returkoden 1.

Terminal window
./check-sites.sh https://coursepress.lnu.se https://coursepress.lnu.se/finns-inte

check-sites.sh:

#!/bin/bash
# Checks that every given URL answers with status 200.
set -euo pipefail
if (($# == 0)); then
echo "Usage: $(basename "$0") <url>..." >&2
exit 1
fi
failed=0
for url in "$@"; do
status=$(curl -s -o /dev/null -w '%{http_code}' "$url" || true)
if [[ $status == 200 ]]; then
echo "OK $status $url"
else
echo "FEL $status $url"
failed=1
fi
done
exit "$failed"

|| true behövs eftersom curl returnerar en felkod när den inte når värden alls, och set -e annars skulle avbryta skriptet mitt i loopen. Returkoden gör att skriptet kan användas av andra skript: ./check-sites.sh "$url" && echo 'Allt svarar'.

Linux-sandlådan under Övningsuppgifter samlar det du har övat på här i en server att göra i ordning, med SSH, användare, rättigheter, loggar och ett större skript.

  • OverTheWire: Bandit, ett spel där du loggar in med SSH och tar dig vidare nivå för nivå med hjälp av kommandona på den här sidan

Inspelningarna om Linux och Bash-skript från 2017 finns kvar i tidigare kursomgångar.

CCBY