<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Scripting Archives - InfoTech Ninja</title>
	<atom:link href="https://infotechninja.com/tag/scripting/feed/" rel="self" type="application/rss+xml" />
	<link>https://infotechninja.com/tag/scripting/</link>
	<description></description>
	<lastBuildDate>Tue, 13 Jan 2026 00:00:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Bash Scripting for Linux SysAdmins: From Beginner to Dangerous</title>
		<link>https://infotechninja.com/bash-scripting-linux/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=bash-scripting-linux</link>
		
		<dc:creator><![CDATA[Morris James]]></dc:creator>
		<pubDate>Tue, 13 Jan 2026 00:00:00 +0000</pubDate>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[SysAdmin]]></category>
		<guid isPermaLink="false">https://infotechninja.com/?p=13</guid>

					<description><![CDATA[<p>Bash scripting is the foundational automation skill for Linux administrators. Before you reach for Python or Ansible, a well-written shell script can handle the majority of day-to-day tasks. This guide goes from variables all the way to a production-ready disk monitoring script.</p>
<p>The post <a href="https://infotechninja.com/bash-scripting-linux/">Bash Scripting for Linux SysAdmins: From Beginner to Dangerous</a> appeared first on <a href="https://infotechninja.com">InfoTech Ninja</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="entry-lead">Bash scripting is the foundational automation skill for Linux administrators. Before you reach for Python or Ansible, a well-written shell script can handle the majority of day-to-day automation tasks — and it runs natively on every Linux system without installing anything. This guide takes you from variables to a complete monitoring script that would be at home on any production server.</p>
<h2>Variables, Input, and Output</h2>
<p>Bash variables are untyped strings by default. Assign without spaces around the equals sign, and reference with a dollar sign prefix. Double-quote your variable references to prevent word splitting on values that contain spaces. Use <code>$(command)</code> syntax (command substitution) to capture command output into a variable. The <code>readonly</code> keyword makes a variable immutable — useful for constants in your scripts.</p>
<p>The <code>read</code> builtin captures user input interactively. For scripts that shouldn&#8217;t be interactive, pass values via positional parameters (<code>$1</code>, <code>$2</code>, etc.) or environment variables. Always validate input: check that required arguments were provided, that file paths exist before operating on them, and that numeric values are actually numeric. Failing fast with a clear error message is far better than letting a script proceed with bad input and silently corrupt data.</p>
<pre><code>#!/usr/bin/env bash
# Variables and I/O basics
set -euo pipefail   # exit on error, undefined vars, pipe failures

# Variables
SCRIPT_NAME="$(basename "$0")"
LOG_DIR="/var/log/myscripts"
DATESTAMP="$(date +%Y%m%d_%H%M%S)"
readonly LOG_DIR

# Positional arguments with default
TARGET_HOST="${1:-localhost}"
PORT="${2:-80}"

# Validate numeric
if ! [[ "$PORT" =~ ^[0-9]+$ ]]; then
    echo "ERROR: PORT must be a number, got: $PORT" >&2
    exit 1
fi

# Read from user interactively
read -rp "Enter backup label: " LABEL
echo "Backing up $TARGET_HOST:$PORT labeled '$LABEL' at $DATESTAMP"</code></pre>
<h2>Conditionals and File Tests</h2>
<p>Bash conditionals use the <code>test</code> command or its synonym <code>[[ ]]</code> (prefer the double-bracket form — it handles empty strings and special characters more safely). File tests are especially useful in sysadmin scripts: <code>-f</code> tests for a regular file, <code>-d</code> for a directory, <code>-r</code> for readable, <code>-w</code> for writable, <code>-x</code> for executable, and <code>-s</code> for non-empty. Combining tests with <code>&amp;&amp;</code> and <code>||</code> inside <code>[[ ]]</code> avoids spawning subshells for each test.</p>
<p>Always check for file existence before operating on it, check for required commands before assuming they&#8217;re available, and check return codes after operations that can fail. The <code>command -v</code> pattern checks whether a command exists in PATH without executing it. Exit codes matter: <code>0</code> is success, anything else is failure. Functions should <code>return</code> meaningful exit codes so callers can react appropriately.</p>
<pre><code>#!/usr/bin/env bash
# Conditionals and file tests

config_file="/etc/myapp/config.yaml"
backup_dir="/backup/$(date +%Y%m%d)"

# Check file exists and is readable
if [[ -f "$config_file" &amp;&amp; -r "$config_file" ]]; then
    echo "Config found: $config_file"
elif [[ -e "$config_file" ]]; then
    echo "ERROR: Config exists but is not readable" >&2; exit 1
else
    echo "ERROR: Config not found at $config_file" >&2; exit 1
fi

# Create backup dir if missing
[[ -d "$backup_dir" ]] || mkdir -p "$backup_dir"

# Check required command exists
if ! command -v rsync &amp;>/dev/null; then
    echo "ERROR: rsync not installed" >&2; exit 1
fi

# Numeric comparison
disk_used=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if (( disk_used > 90 )); then
    echo "WARNING: Root partition ${disk_used}% full"
fi</code></pre>
<h2>Loops: for, while, until</h2>
<p>Bash provides three loop constructs. The <code>for</code> loop iterates over a list or glob expansion — invaluable for processing multiple files, hosts, or values. The <code>while</code> loop continues as long as a condition is true, commonly used with <code>read</code> to process file contents line by line. The <code>until</code> loop is the inverse: it continues until a condition becomes true, useful for polling until a service becomes available or a file appears.</p>
<p>Avoid the common pitfall of <code>for file in $(ls /path/)</code> — it breaks on filenames with spaces. Use glob expansion directly: <code>for file in /path/*.log</code>. When reading files line by line, use the <code>while IFS= read -r line</code> pattern — the <code>IFS=</code> prevents leading/trailing whitespace from being stripped, and <code>-r</code> prevents backslash interpretation. These small details matter when your scripts need to handle real-world filenames and content.</p>
<pre><code>#!/usr/bin/env bash
# Loop examples

# for loop — process multiple servers
servers=("web01" "web02" "db01" "db02")
for server in "${servers[@]}"; do
    echo "Checking $server..."
    if ping -c1 -W2 "$server" &amp;>/dev/null; then
        echo "  $server: ONLINE"
    else
        echo "  $server: OFFLINE" >&2
    fi
done

# Process log file line by line
while IFS= read -r line; do
    if [[ "$line" == *"ERROR"* ]]; then
        echo "Found error: $line"
    fi
done < /var/log/app/app.log

# until loop — wait for a service to respond
port=5432
until nc -z localhost "$port" 2>/dev/null; do
    echo "Waiting for port $port to open..."
    sleep 3
done
echo "Service on port $port is ready."</code></pre>
<h2>Building a Disk Monitoring Script</h2>
<p>Putting the pieces together: a complete disk monitoring script that checks disk usage across specified mount points, logs warnings when thresholds are exceeded, and sends an email alert when a critical threshold is hit. Schedule it with cron to run every 15 minutes: <code>*/15 * * * * /usr/local/bin/disk-monitor.sh</code>.</p>
<pre><code>#!/usr/bin/env bash
# disk-monitor.sh — Check disk usage and alert on threshold breach
set -euo pipefail

# Configuration
WARN_THRESHOLD=80
CRIT_THRESHOLD=90
ALERT_EMAIL="admin@example.com"
LOG_FILE="/var/log/disk-monitor.log"
MOUNT_POINTS=("/" "/var" "/home" "/data")
HOSTNAME="$(hostname -f)"
TIMESTAMP="$(date '+%Y-%m-%d %H:%M:%S')"

# Function: log a message
log() { echo "[$TIMESTAMP] $*" | tee -a "$LOG_FILE"; }

# Function: send alert email
send_alert() {
    local mount="$1" used="$2"
    echo "CRITICAL: Disk usage on $HOSTNAME:$mount is at ${used}%" | \
        mail -s "[DISK ALERT] $HOSTNAME $mount at ${used}%" "$ALERT_EMAIL"
    log "ALERT sent for $mount at ${used}%"
}

alert_needed=false

for mp in "${MOUNT_POINTS[@]}"; do
    [[ -d "$mp" ]] || { log "SKIP: $mp not found"; continue; }
    used=$(df "$mp" | awk 'NR==2 {print $5}' | tr -d '%')

    if (( used >= CRIT_THRESHOLD )); then
        log "CRITICAL: $mp is at ${used}%"
        send_alert "$mp" "$used"
        alert_needed=true
    elif (( used >= WARN_THRESHOLD )); then
        log "WARNING: $mp is at ${used}%"
    else
        log "OK: $mp is at ${used}%"
    fi
done

$alert_needed &amp;&amp; exit 2
exit 0</code></pre>
<p>The post <a href="https://infotechninja.com/bash-scripting-linux/">Bash Scripting for Linux SysAdmins: From Beginner to Dangerous</a> appeared first on <a href="https://infotechninja.com">InfoTech Ninja</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">31</post-id>	</item>
	</channel>
</rss>
