Skip to content

Some Scripts

Script to unzip all zip files from sub-directory

#!/usr/bin/env bash
# unzip-all.sh — Recursively unzip every .zip under a directory
# Usage: ./unzip-all.sh [ROOT_DIR]
# Default ROOT_DIR is the current directory.

set -euo pipefail

ROOT_DIR="${1:-.}"
LOGFILE="unzip_$(date +%F_%H%M%S).log"

# Check dependency
if ! command -v unzip >/dev/null 2>&1; then
  echo "Error: 'unzip' is not installed. Install it and retry." >&2
  exit 1
fi

echo "Starting unzip at: $(date)" | tee -a "$LOGFILE"
echo "Root: $(readlink -f "$ROOT_DIR")" | tee -a "$LOGFILE"

# Find .zip files robustly (handles spaces/newlines)
# -iname to catch .ZIP/.Zip etc.
# unzip flags:
#   -n  never overwrite existing files
#   -q  quiet (logs still go to $LOGFILE)
#   -d  destination directory (the zip's parent dir)
find "$ROOT_DIR" -type f -iname '*.zip' -print0 |
while IFS= read -r -d '' ZIP; do
  DEST_DIR="$(dirname "$ZIP")"
  echo "Unzipping: $ZIP -> $DEST_DIR" | tee -a "$LOGFILE"
  if unzip -n -q "$ZIP" -d "$DEST_DIR" >>"$LOGFILE" 2>&1; then
    echo "OK: $ZIP" | tee -a "$LOGFILE"
  else
    echo "FAILED: $ZIP (see $LOGFILE)" | tee -a "$LOGFILE"
  fi
done

echo "Done at: $(date)" | tee -a "$LOGFILE"

Script to list k8s single node resource allocations

#!/usr/bin/env bash
set -euo pipefail

# Requirements: kubectl, jq, awk, sed
have_cmd() { command -v "$1" >/dev/null 2>&1; }
abort(){ echo "Error: $*" >&2; exit 1; }
need(){ for c in "$@"; do have_cmd "$c" || abort "Missing dependency: $c"; done; }
need kubectl jq awk sed

HAVE_TOP=1
kubectl top pods -A >/dev/null 2>&1 || HAVE_TOP=0

HAVE_DFPV=1
kubectl df-pv >/dev/null 2>&1 || HAVE_DFPV=0

TMPDIR="$(mktemp -d)"; trap 'rm -rf "$TMPDIR"' EXIT

# -------------------- POD COUNT --------------------
kubectl get pods -A --no-headers 2>/dev/null \
| awk '{cnt[$1]++} END{for (ns in cnt) print ns, cnt[ns]}' > "$TMPDIR/pods.txt" || true

# -------------------- Requests/Limits per container (normalized in jq) --------------------
# We compute CPU in CORES and Memory in Gi directly in jq to avoid shell math issues.
kubectl get pods -A -o json \
| jq -r '
  def toGi:
    if . == null then 0
    elif type=="number" then (. / (1024*1024*1024))
    elif test("m$")  then (sub("m$";"") | tonumber) / 1000 / (1024*1024*1024)    # milli-bytes -> Gi
    elif test("Ki$") then (sub("Ki$";"")|tonumber) / 1024 / 1024
    elif test("Mi$") then (sub("Mi$";"")|tonumber) / 1024
    elif test("Gi$") then (sub("Gi$";"")|tonumber)
    elif test("Ti$") then (sub("Ti$";"")|tonumber) * 1024
    elif test("Pi$") then (sub("Pi$";"")|tonumber) * 1024 * 1024
    elif test("Ei$") then (sub("Ei$";"")|tonumber) * 1024 * 1024 * 1024
    elif test("K$")  then (sub("K$";"") | tonumber) * 1000 / (1024*1024*1024)
    elif test("M$")  then (sub("M$";"") | tonumber) * 1000000 / (1024*1024*1024)
    elif test("G$")  then (sub("G$";"") | tonumber) * 1000000000 / (1024*1024*1024)
    elif test("T$")  then (sub("T$";"") | tonumber) * 1000000000000 / (1024*1024*1024)
    else (tonumber / (1024*1024*1024))  # raw bytes
    end;

  def toCores:
    if . == null then 0
    elif type=="number" then .
    elif test("m$") then (sub("m$";"")|tonumber)/1000
    else (tonumber)
    end;

  .items[]
  | .metadata.namespace as $ns
  | ( [.spec.containers[]?] + [.spec.initContainers[]?] )[]
  | [
      $ns,
      ((.resources.requests.cpu   // "0") | toCores),    # cores
      ((.resources.limits.cpu     // "0") | toCores),    # cores
      ((.resources.requests.memory // "0") | toGi),      # Gi
      ((.resources.limits.memory   // "0") | toGi)       # Gi
    ]
  | @tsv
' > "$TMPDIR/rl_by_container.tsv"

# Sum to namespace totals
awk '{reqc[$1]+=$2} END{for (k in reqc) printf "%s %.6f\n", k, reqc[k]}' "$TMPDIR/rl_by_container.tsv" > "$TMPDIR/req_cpu_cores.txt"
awk '{limc[$1]+=$3} END{for (k in limc) printf "%s %.6f\n", k, limc[k]}' "$TMPDIR/rl_by_container.tsv" > "$TMPDIR/lim_cpu_cores.txt"
awk '{reqm[$1]+=$4} END{for (k in reqm) printf "%s %.6f\n", k, reqm[k]}' "$TMPDIR/rl_by_container.tsv" > "$TMPDIR/req_mem_gi.txt"
awk '{limm[$1]+=$5} END{for (k in limm) printf "%s %.6f\n", k, limm[k]}' "$TMPDIR/rl_by_container.tsv" > "$TMPDIR/lim_mem_gi.txt"

# -------------------- Actual usage (from metrics-server) --------------------
if [[ $HAVE_TOP -eq 1 ]]; then
  kubectl top pods -A --no-headers 2>/dev/null \
  | awk '
      {
        ns=$1; cpu=$3; mem=$4;
        # CPU in millicores -> cores
        gsub(/m$/,"",cpu);
        if (cpu!="") cpu_m[ns]+=cpu;

        # Memory: handle Gi/Mi/Ki or bytes
        if (mem ~ /Gi$/) { sub(/Gi$/,"",mem); mem_gi[ns]+=mem+0; }
        else if (mem ~ /Mi$/) { sub(/Mi$/,"",mem); mem_gi[ns]+=(mem+0)/1024.0; }
        else if (mem ~ /Ki$/) { sub(/Ki$/,"",mem); mem_gi[ns]+=(mem+0)/(1024.0*1024.0); }
        else { gsub(/[^0-9.]/,"",mem); if (mem!="") mem_gi[ns]+=(mem+0)/(1024.0*1024.0*1024.0); }
      }
      END{
        for (ns in cpu_m) printf "CPU %s %.6f\n", ns, cpu_m[ns]/1000.0;
        for (ns in mem_gi) printf "MEM %s %.6f\n", ns, mem_gi[ns];
      }
    ' > "$TMPDIR/top_sums.txt" || true

  awk '/^CPU /{print $2, $3}' "$TMPDIR/top_sums.txt" > "$TMPDIR/used_cpu_cores.txt" || true
  awk '/^MEM /{print $2, $3}' "$TMPDIR/top_sums.txt" > "$TMPDIR/used_mem_gi.txt"   || true
else
  : > "$TMPDIR/used_cpu_cores.txt"
  : > "$TMPDIR/used_mem_gi.txt"
fi

# -------------------- PVC count and usage --------------------
kubectl get pvc -A --no-headers 2>/dev/null | awk '{cnt[$1]++} END{for (ns in cnt) print ns, cnt[ns]}' > "$TMPDIR/pvc_count.txt" || true

PVC_NOTE=""
if [[ $HAVE_DFPV -eq 1 ]]; then
  kubectl df-pv --no-headers 2>/dev/null \
  | awk '
      {
        ns=$1; used=$6;
        if (used ~ /Gi$/) { sub(/Gi$/,"",used); val=used+0; }
        else if (used ~ /Mi$/) { sub(/Mi$/,"",used); val=(used+0)/1024.0; }
        else if (used ~ /Ki$/) { sub(/Ki$/,"",used); val=(used+0)/(1024.0*1024.0); }
        else { gsub(/[^0-9.]/,"",used); val=(used+0)/(1024.0*1024.0*1024.0); }
        sum[ns]+=val;
      }
      END{ for (ns in sum) printf "%s %.6f\n", ns, sum[ns]; }
    ' > "$TMPDIR/pvc_used_gi.txt" || true
else
  PVC_NOTE="(PVC Usage shows capacity because 'kubectl df-pv' is not installed)"
  kubectl get pvc -A -o json 2>/dev/null \
  | jq -r '
      def toGi:
        if . == null then 0
        elif type=="number" then (. / (1024*1024*1024))
        elif test("Ki$") then (sub("Ki$";"")|tonumber)/1024/1024
        elif test("Mi$") then (sub("Mi$";"")|tonumber)/1024
        elif test("Gi$") then (sub("Gi$";"")|tonumber)
        elif test("Ti$") then (sub("Ti$";"")|tonumber)*1024
        elif test("Pi$") then (sub("Pi$";"")|tonumber)*1024*1024
        elif test("Ei$") then (sub("Ei$";"")|tonumber)*1024*1024*1024
        elif test("K$")  then (sub("K$";"") |tonumber)*1000/(1024*1024*1024)
        elif test("M$")  then (sub("M$";"") |tonumber)*1000000/(1024*1024*1024)
        elif test("G$")  then (sub("G$";"") |tonumber)*1000000000/(1024*1024*1024)
        elif test("T$")  then (sub("T$";"") |tonumber)*1000000000000/(1024*1024*1024)
        else (tonumber / (1024*1024*1024))
        end;
      .items[]
      | [.metadata.namespace, ((.status.capacity.storage // .spec.resources.requests.storage // "0") | toGi)]
      | @tsv
    ' \
  | awk '{sum[$1]+=$2} END{for (ns in sum) printf "%s %.6f\n", ns, sum[ns]}' > "$TMPDIR/pvc_used_gi.txt" || true
fi

# -------------------- Collect namespaces --------------------
awk '{print $1}' \
  "$TMPDIR/pods.txt" \
  "$TMPDIR/req_cpu_cores.txt" "$TMPDIR/lim_cpu_cores.txt" \
  "$TMPDIR/used_cpu_cores.txt" "$TMPDIR/req_mem_gi.txt" \
  "$TMPDIR/lim_mem_gi.txt" "$TMPDIR/used_mem_gi.txt" \
  "$TMPDIR/pvc_count.txt" "$TMPDIR/pvc_used_gi.txt" 2>/dev/null \
| sort -u > "$TMPDIR/all_ns.txt"

# -------------------- Print table --------------------
awk -v pods="$TMPDIR/pods.txt" \
    -v rcc="$TMPDIR/req_cpu_cores.txt" \
    -v lcc="$TMPDIR/lim_cpu_cores.txt" \
    -v ucc="$TMPDIR/used_cpu_cores.txt" \
    -v rmg="$TMPDIR/req_mem_gi.txt" \
    -v lmg="$TMPDIR/lim_mem_gi.txt" \
    -v umg="$TMPDIR/used_mem_gi.txt" \
    -v pvc="$TMPDIR/pvc_count.txt" \
    -v pvcg="$TMPDIR/pvc_used_gi.txt" '
  function load(file, arr){ while((getline < file)>0){ arr[$1]=$2 } close(file) }
  function rep(n){ s=""; for(i=0;i<n;i++) s=s"-"; return s }
  BEGIN{
    load(pods,P); load(rcc,RCC); load(lcc,LCC); load(ucc,UCC);
    load(rmg,RMG); load(lmg,LMG); load(umg,UMG); load(pvc,PVC); load(pvcg,PVCG);

    printf "%-32s %6s %12s %12s %14s %14s %14s %14s %6s %14s\n",
      "NAMESPACE","PODS","REQ_CPU","LIM_CPU","CPU_USED","REQ_MEM(Gi)","LIM_MEM(Gi)","MEM_USED(Gi)","PVCs","PVC_USED(Gi)";
    printf "%-32s %6s %12s %12s %14s %14s %14s %14s %6s %14s\n",
      rep(32),rep(6),rep(12),rep(12),rep(14),rep(14),rep(14),rep(14),rep(6),rep(14);
  }
  {
    ns=$0
    printf "%-32s %6s %12.3f %12.3f %14s %14.3f %14.3f %14s %6s %14.3f\n",
      ns,
      (ns in P ? P[ns] : 0),
      (ns in RCC ? RCC[ns]+0.0 : 0.0),
      (ns in LCC ? LCC[ns]+0.0 : 0.0),
      (ns in UCC ? sprintf("%.3f", UCC[ns]+0.0) : "N/A"),
      (ns in RMG ? RMG[ns]+0.0 : 0.0),
      (ns in LMG ? LMG[ns]+0.0 : 0.0),
      (ns in UMG ? sprintf("%.3f", UMG[ns]+0.0) : "N/A"),
      (ns in PVC ? PVC[ns] : 0),
      (ns in PVCG ? PVCG[ns]+0.0 : 0.0)
  }
' "$TMPDIR/all_ns.txt" | column -t

# -------------------- Notes --------------------
if [[ $HAVE_TOP -eq 0 ]]; then
  echo ""
  echo "Note: 'kubectl top' not available — CPU_USED and MEM_USED show 'N/A'. Install/enable metrics-server to populate actual usage."
fi
if [[ -n "$PVC_NOTE" ]]; then
  echo "Note: $PVC_NOTE"
fi