Bash Scripting

Bash Scripting — Complete Guide

🚀 Bash Scripting — Complete Guide

Panduan Lengkap Belajar Bash Scripting dari Nol hingga Mahir

1. Pengertian Bash Script

Bash adalah shell sekaligus scripting language di Linux. Script bash = kumpulan command Linux yang dijalankan berurutan secara otomatis.

Struktur Dasar Script

#!/bin/bash
# WAJIB ada di baris pertama (shebang)
# Kasih tau OS interpreter apa yang dipakai

# Ini komentar (nggak dieksekusi)
echo "Hello World"

Cara Menjalankan Script

$ chmod +x script.sh          # Kasih permission execute
$ ./script.sh                 # Jalankan script
$ bash script.sh              # Atau pakai bash interpreter

ℹ️ Info: Shebang

#!/bin/bash adalah shebang yang memberitahu OS untuk menggunakan bash interpreter saat menjalankan script.

2. Variable & Input/Output

2.1 Deklarasi Variable

#!/bin/bash

# Deklarasi variable (TANPA spasi di kiri & kanan =)
nama="Ani Utami"           # String
umur=25                    # Integer
pi=3.14                    # Float

# Gunakan variable dengan prefix $
echo $nama                 # Output: Ani Utami
echo "Nama gua: $nama"     # Output: Nama gua: Ani Utami

# Gunakan curly braces untuk safe
echo ${nama}               # Output: Ani Utami
echo "${nama}!"            # Output: Ani Utami!

⚠️ Hati-hati: Spasi di Deklarasi

SALAH: nama = "Ani"
BENAR: nama="Ani"
Bash akan treat spasi sebagai delimiter command!

2.2 Jenis-Jenis Variable

Jenis Contoh Penjelasan
User-Defined server="192.168.1.1" Variable yang kita buat sendiri
Environment $HOME, $USER, $PATH Variable dari sistem
Special $0, $1, $#, $? Variable built-in bash
Readonly readonly MAX=3 Konstanta (nggak bisa diubah)

2.3 Special Variable

#!/bin/bash

# Argument dari command line
echo $0    # Nama script itu sendiri
echo $1    # Argument pertama
echo $2    # Argument kedua
echo $#    # Jumlah total argument
echo $@    # Semua argument
echo $?    # Exit code command terakhir (0=sukses, 1=error)
echo $$    # PID script
echo $!    # PID background process

# Contoh:
# ./script.sh server01 22 admin
# $0 = ./script.sh
# $1 = server01
# $2 = 22
# $3 = admin
# $# = 3

2.4 Input dari User

#!/bin/bash

# read — baca input user
read nama
echo "Halo $nama"

# read dengan prompt
read -p "Username: " username
echo "Username: $username"

# read password (tersembunyi)
read -sp "Password: " password
echo ""
echo "Password disimpan"

# read dengan timeout (5 detik)
read -t 5 -p "Input (5 detik): " input

2.5 Output & Redirect

#!/bin/bash

echo "Normal output"               # Dengan newline
echo -n "Tanpa newline"            # Tanpa newline
echo -e "Tab:\there\nNewline"      # Interpret escape character

# Redirect output
echo "Log" >> /var/log/script.log  # Append ke file
echo "Override" > /tmp/output.txt  # Overwrite file
echo "Error" >&2                   # Output ke stderr

2.6 Command Substitution

#!/bin/bash

# Simpan output command ke variable (Cara 1: Recommended)
tanggal=$(date +%Y-%m-%d)
hostname=$(hostname)
ip=$(hostname -I | awk '{print $1}')

echo "Tanggal: $tanggal"
echo "Server: $hostname"
echo "IP: $ip"

# Arithmetic (operasi matematika)
a=10
b=3

hasil=$((a + b))      # 13
kurang=$((a - b))     # 7
kali=$((a * b))       # 30
bagi=$((a / b))       # 3
modulo=$((a % b))     # 1

echo "Hasil: $hasil"

3. Conditional (IF / CASE)

3.1 IF Statement

#!/bin/bash

# Struktur dasar
# if [ kondisi ]; then
#     perintah kalau TRUE
# elif [ kondisi_lain ]; then
#     perintah kalau kondisi_lain TRUE
# else
#     perintah kalau semua FALSE
# fi

nilai=85

if [ $nilai -ge 90 ]; then
    echo "Grade A"
elif [ $nilai -ge 80 ]; then
    echo "Grade B"
elif [ $nilai -ge 70 ]; then
    echo "Grade C"
else
    echo "Grade D"
fi

3.2 Operator Perbandingan

Operator Arti Contoh
-eq Equal (==) [ $a -eq 10 ]
-ne Not equal (!=) [ $a -ne 10 ]
-gt Greater than (>) [ $a -gt 10 ]
-lt Less than (<) [ $a -lt 10 ]
-ge Greater or equal (>=) [ $a -ge 10 ]
-le Less or equal (<=) [ $a -le 10 ]

3.3 String Comparison

#!/bin/bash

os="ubuntu"

if [ "$os" = "ubuntu" ]; then     # SAMA
    echo "Ubuntu detected"
fi

if [ "$os" != "centos" ]; then    # BERBEDA
    echo "Bukan CentOS"
fi

if [ -z "$os" ]; then             # KOSONG (zero length)
    echo "OS kosong"
fi

if [ -n "$os" ]; then             # TIDAK KOSONG
    echo "OS ada isinya: $os"
fi

3.4 File & Directory Check

#!/bin/bash

file="/etc/passwd"
dir="/var/log"

if [ -f "$file" ]; then           # Ada & FILE
    echo "$file adalah file"
fi

if [ -d "$dir" ]; then            # Ada & DIREKTORI
    echo "$dir adalah direktori"
fi

if [ -e "$file" ]; then           # Exist (apapun)
    echo "$file exist"
fi

if [ -r "$file" ]; then           # Readable
    echo "Bisa dibaca"
fi

if [ -w "$file" ]; then           # Writable
    echo "Bisa ditulis"
fi

if [ -x "$file" ]; then           # Executable
    echo "Bisa dijalankan"
fi

if [ -s "$file" ]; then           # Tidak kosong
    echo "File punya isi"
fi

3.5 Logical Operator

#!/bin/bash

umur=25
nama="ani"

# AND
if [ $umur -gt 18 ] && [ -n "$nama" ]; then
    echo "Umur > 18 DAN nama ada"
fi

# OR
if [ $umur -lt 18 ] || [ "$nama" = "admin" ]; then
    echo "Umur < 18 ATAU nama admin"
fi

# NOT
if ! [ -f "/etc/nonexist" ]; then
    echo "File tidak ada"
fi

# Double bracket (lebih modern)
if [[ $umur -gt 18 && -n "$nama" ]]; then
    echo "Double bracket AND"
fi

3.6 CASE Statement

#!/bin/bash

read -p "Pilih OS (ubuntu/centos/debian): " os

case $os in
    ubuntu|Ubuntu)
        echo "Ubuntu dipilih"
        apt update
        ;;
    centos|CentOS)
        echo "CentOS dipilih"
        yum update
        ;;
    debian|Debian)
        echo "Debian dipilih"
        apt update
        ;;
    *)                    # Default
        echo "OS tidak dikenal: $os"
        exit 1
        ;;
esac

4. Looping (FOR, WHILE, UNTIL)

4.1 FOR Loop

#!/bin/bash

# Cara 1: List manual
for buah in apel mangga pisang jeruk; do
    echo "Buah: $buah"
done

# Cara 2: Range angka
for i in {1..5}; do
    echo "Nomor: $i"
done

# Cara 3: C-style for
for ((i=0; i<5; i++)); do
    echo "i = $i"
done

# Cara 4: Iterasi file
for file in /var/log/*.log; do
    echo "Log file: $file"
done

# Cara 5: Iterasi output command
for user in $(cat /etc/passwd | cut -d: -f1); do
    echo "User: $user"
done

4.2 WHILE Loop

#!/bin/bash

# Basic while
i=1
while [ $i -le 5 ]; do
    echo "Iterasi: $i"
    i=$((i + 1))         # PENTING! Increment
done

# Read file line by line
while IFS= read -r line; do
    echo "Baris: $line"
done < /etc/hosts

# Infinite loop dengan break
while true; do
    read -p "Input (ketik 'exit' untuk keluar): " input
    if [ "$input" = "exit" ]; then
        break
    fi
    echo "Lu input: $input"
done

# Retry mechanism (praktis!)
MAX_RETRY=3
retry=0

while [ $retry -lt $MAX_RETRY ]; do
    ping -c 1 8.8.8.8 > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo "✓ Internet OK"
        break
    else
        retry=$((retry + 1))
        echo "✗ Retry $retry/$MAX_RETRY..."
        sleep 2
    fi
done

4.3 Loop Control (break & continue)

#!/bin/bash

# BREAK — Stop loop sepenuhnya
for i in {1..10}; do
    if [ $i -eq 6 ]; then
        echo "Ketemu 6, stop!"
        break
    fi
    echo $i
done
# Output: 1 2 3 4 5 Ketemu 6, stop!

# CONTINUE — Skip iterasi ini
for i in {1..10}; do
    if [ $i -eq 5 ] || [ $i -eq 7 ]; then
        continue
    fi
    echo $i
done
# Output: 1 2 3 4 6 8 9 10

# BREAK nested loop
for i in {1..3}; do
    for j in {1..3}; do
        if [ $j -eq 2 ]; then
            break 2      # Break 2 level
        fi
        echo "i=$i j=$j"
    done
done

5. Function

5.1 Deklarasi & Panggil Function

#!/bin/bash

# Cara 1: Pakai keyword function
function sapa() {
    echo "Halo $1!"      # $1 = argument pertama
}

# Cara 2: Tanpa keyword function
cek_port() {
    local host=$1       # local = variable hanya di function
    local port=$2
    
    timeout 2 bash -c "cat < /dev/null > /dev/tcp/$host/$port" 2>/dev/null
    
    if [ $? -eq 0 ]; then
        echo "✓ $host:$port OPEN"
        return 0        # Return value (exit code)
    else
        echo "✗ $host:$port CLOSED"
        return 1
    fi
}

# Panggil function
sapa "Ani"              # Output: Halo Ani!
sapa "World"            # Output: Halo World!

cek_port "google.com" 443

# Tangkap return value
if [ $? -eq 0 ]; then
    echo "Google port 443 OK"
fi

5.2 Local vs Global Variable

#!/bin/bash

x=10                    # Global

ubah_x() {
    local x=99          # Local — nggak affect global x
    echo "Di dalam function: x=$x"
}

ubah_x                  # Output: Di dalam function: x=99
echo "Di luar function: x=$x"  # Output: Di luar function: x=10

6. Array

6.1 Array Dasar

#!/bin/bash

# Deklarasi array
servers=("server1" "server2" "server3")
ports=(22 80 443 3306)

# Akses element (index mulai 0)
echo ${servers[0]}      # server1
echo ${servers[1]}      # server2
echo ${servers[-1]}     # server3 (index terakhir)

# Semua element
echo ${servers[@]}      # server1 server2 server3

# Jumlah element
echo ${#servers[@]}     # 3

# Tambah element
servers+=("server4")

# Hapus element
unset servers[1]

# Iterasi array
for server in "${servers[@]}"; do
    echo "Server: $server"
done

6.2 Associative Array (Dictionary)

#!/bin/bash

# HARUS declare dulu!
declare -A user_info

user_info[nama]="Ani Utami"
user_info[email]="ani@lks2025.id"
user_info[role]="vpn,mail"

echo ${user_info[nama]}     # Ani Utami
echo ${user_info[email]}    # ani@lks2025.id

# Iterasi associative array
for key in "${!user_info[@]}"; do
    echo "$key = ${user_info[$key]}"
done

7. Contoh Praktis — LDAP User Creator

7.1 Script Lengkap

#!/bin/bash
# Script: create_ldap_users.sh
# Fungsi: Buat multiple user LDAP dari CSV

set -euo pipefail

# ============================================
# KONFIGURASI
# ============================================
LDAP_HOST="ldap://ldap.lks:389"
LDAP_ADMIN_DN="cn=admin,dc=lks,dc=local"
LDAP_BASE_DN="dc=lks,dc=local"
PEOPLE_OU="ou=people,dc=lks,dc=local"
GROUPS_OU="ou=groups,dc=lks,dc=local"
DEFAULT_SHELL="/bin/bash"
DEFAULT_PASSWORD="Skills2025!"

# ============================================
# FUNCTION DEFINITIONS
# ============================================

log_info() { echo "[INFO]  $(date '+%H:%M:%S') $1"; }
log_ok()   { echo "[OK]    $(date '+%H:%M:%S') $1"; }
log_err()  { echo "[ERROR] $(date '+%H:%M:%S') $1" >&2; }

generate_hash() {
    slappasswd -s "$1"
}

user_exists() {
    ldapsearch -x -H "$LDAP_HOST" \
        -D "$LDAP_ADMIN_DN" -w "$LDAP_PASS" \
        -b "$LDAP_BASE_DN" "(uid=$1)" uid 2>/dev/null | grep -q "uid: $1"
}

add_to_group() {
    local uid=$1
    local group=$2
    log_info "Tambah $uid ke group $group..."
    ldapmodify -x -H "$LDAP_HOST" \
        -D "$LDAP_ADMIN_DN" -w "$LDAP_PASS" << EOF
dn: cn=$group,$GROUPS_OU
changetype: modify
add: memberUid
memberUid: $uid
EOF
}

# ============================================
# CEK ARGUMENT
# ============================================

if [ $# -lt 1 ]; then
    echo "Usage: $0 "
    echo "Format: username,fullname,email,uid_number,groups"
    exit 1
fi

CSV_FILE=$1
[ ! -f "$CSV_FILE" ] && { log_err "File tidak ditemukan"; exit 1; }

# ============================================
# INPUT PASSWORD & PROSES
# ============================================

read -sp "LDAP Admin Password: " LDAP_PASS
echo ""

log_info "Memproses $CSV_FILE..."
success=0
failed=0

while IFS=',' read -r username fullname email uid_number groups; do
    [[ -z "$username" || "$username" == \#* ]] && continue

    log_info "Proses: $username ($fullname)"

    if user_exists "$username"; then
        log_err "User $username sudah ada!"
        ((failed++))
        continue
    fi

    pass_hash=$(generate_hash "$DEFAULT_PASSWORD")

    ldapadd -x -H "$LDAP_HOST" \
        -D "$LDAP_ADMIN_DN" -w "$LDAP_PASS" << EOF
dn: uid=$username,$PEOPLE_OU
objectClass: inetOrgPerson
objectClass: posixAccount
uid: $username
cn: $fullname
sn: ${fullname##* }
mail: $email
userPassword: $pass_hash
uidNumber: $uid_number
gidNumber: $uid_number
homeDirectory: /home/$username
loginShell: $DEFAULT_SHELL
EOF

    if [ $? -eq 0 ]; then
        log_ok "User $username dibuat"
        
        IFS=';' read -ra group_list <<< "$groups"
        for group in "${group_list[@]}"; do
            group=$(echo "$group" | tr -d ' ')
            [ -z "$group" ] && continue
            add_to_group "$username" "$group"
            log_ok "  $username → $group"
        done

        ((success++))
    else
        log_err "Gagal buat user $username"
        ((failed++))
    fi

done < "$CSV_FILE"

# ============================================
# SUMMARY
# ============================================

echo ""
echo "==============================="
echo "SUMMARY:"
echo "  Berhasil: $success user"
echo "  Gagal   : $failed user"
echo "==============================="

7.2 CSV Input File (users.csv)

# username,fullname,email,uid_number,groups
ani,Ani Utami,ani@lks2025.id,1001,mail-users;vpn-users
adi,Adi Santoso,adi@lks2025.id,1002,vpn-users
skills39,Skills LKS,skills39@lks2025.id,1003,mail-users;vpn-users

💡 Tips: Jalankan Script

$ chmod +x create_ldap_users.sh
$ ./create_ldap_users.sh users.csv
# Input: LDAP Admin Password: (ketik password)

8. Error Handling

8.1 Exit Code & set -e

#!/bin/bash

# set -e — Script berhenti otomatis saat error
# set -u — Error kalau ada unset variable
# set -o pipefail — Error kalau ada pipe yang fail

set -euo pipefail

# Biasanya ditulis singkat:
# set -euo pipefail

# Cek exit code
ls /etc/passwd > /dev/null 2>&1
echo "Exit code: $?"    # 0 (sukses)

ls /nonexist > /dev/null 2>&1
echo "Exit code: $?"    # 2 (error)

8.2 TRAP — Error Handler

#!/bin/bash

# Jalankan cleanup saat script error/exit
cleanup() {
    echo "Cleanup dijalankan..."
    rm -f /tmp/temp_file
}

trap cleanup EXIT        # Jalankan saat EXIT (apapun)
trap cleanup ERR         # Jalankan saat ERROR

# ============================================
# Error handling custom
# ============================================

log_error() {
    echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $1" >&2
}

log_info() {
    echo "[INFO]  $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

if ! useradd testuser 2>/dev/null; then
    log_error "Gagal buat user testuser"
    exit 1
fi

log_info "User testuser berhasil dibuat"

9. Glosarium

Istilah Penjelasan
Shebang #!/bin/bash — Kasih tau OS pakai interpreter apa
Exit Code Angka yang dikembalikan command (0=sukses, non-zero=error)
$? Variable special — simpan exit code command terakhir
local Variable hanya hidup di dalam function
IFS Internal Field Separator — delimiter default (spasi, tab, newline)
Subshell Process baru yang dijalankan dalam $() atau ()
set -e Exit script otomatis kalau ada error
trap Tangkap signal/event (EXIT, ERR) → jalankan function
Pipe (|) Sambung output command kiri ke input command kanan
Redirect (>, >>) Alihkan output ke file (overwrite / append)

Bash Scripting — Complete Guide

Dibuat dengan 💪 untuk LKS & Linux Enthusiasts

Selamat belajar! Keep coding! 🚀

Comments

Popular posts from this blog

Apa itu Link Aggregation?

Apa Itu Port Security di Switch Cisco