Bashing the scraper

Av anledningar som vi inte behöver gå in på satt jag och pillade på ett bashscript på jobb idag, och lärde mig lite om curl

result=$(curl -s -d "iporfqdn=$line" http://some.place.com/toogle/ | sed -e 's/<[^>]*>//g' | awk '/NTP/ { getline; print $3 }')

-d gör att curl postar ett formulärs fält, i fallet ovan som har id=iporfqdn. Jag är övertygad om att man kan skippa sed-pipen och rensa bort html-taggarna med enkom awk, men det bidde inte så i det här skriptet.

Just awk '/NTP/ { getline; print $3 }') är en smart konstruktion för scraping, som bearbetar raden efter strängen ”NTP” stöts på. I mitt fall innehöll den viktiga raden jag vill åt bara variabler som inte gick smidigt att göra en regexp på.

En annan sak som jag blev påmind om var att en klassisk ”läs en rad i taget från en textfil”-loop kan bli onödigt krånglig. En vanlig metod är att använda sig av:

while read line; do
# gör något, typ echo $line
done

Men då läses inte textfilens sista rad in, om sista variabeln är på samma rad som sista \n

Lösningen? Man kan lägga till en annan delimiter än newline och testa, och se till att read inte tolkar slashen i newline; \n som en escape character:

while IFS='' read -r line || [ -n "$line" ]; do
result=$(someFunction $line)
echo $result
let count++
done < "$1"

Här skickar vi input från varje rad i en textfil (från $1). Det kan vara en lista med IP-addresser, lösenord, namn, filmer, artikel- eller ordernummer, telefonnummer, orter, fotbollslag -- eller vad man nu kan tänkas behöva ge som input till något annat.
read -r är tricket för att undvika newline-escape!
[ -n "$variabel" ] kollar om strängen är NULL, men då krävs att den är inom citationstecken. När vi når efter sista raden återstår ...inget. Färdigt!

Find out if your system needs a diet

At work a colleague was working on making a Linux distro fit for a thin client, taking off all the fat. While there are many ways to optimize system resources, a simple start is to remove all unnecessary files and review if large files can be replaced by smaller ones (think busybox etc.). This inspired me to make the script below.

#!/bin/bash
# siezesize.sh

# Simple report to check for largest file sizes in a given directory.
# Script by D. Cervera, 2010 
version="0.2"

# Notes:
# Works recursively from the input path. 
# Requires root to parse all files and directories.
# Excludes all but -f (regular files).
# Shows top 10 largest files and directories.
# Prompts user to display a sorted list of all files from input path.

USAGE="Usage: `basename $0` [/path]\n Be root or miss out.\n"
userpath="$1" # Get path from user input

# Check input
[ ! -d "$userpath" ] && { echo -e "\n $USAGE\n"; exit; }

# List all files in size order, display ten largest
FILESIZE=`find $userpath -type f -exec du -kx {} \; | sort -nr | head`
echo -e "\n TOP TEN FILE SIZE list:\n\nBYTES\tFILE\n$FILESIZE"

# The weight of directories, show ten largest
DIRECTORYWEIGHT=`du -kx $userpath | sort -nr | head`
echo -e "\n TOP TEN DIRECTORY WEIGHT list:\n\nBYTES\tDIRECTORY\n$DIRECTORYWEIGHT\n" 

echo -en "\n Display all files from $userpath? (y/n): "
read ANSWER
case $ANSWER in
	[yY])	echo -e " This can take a while.\n\nBYTES\tFILE" 
		ALLFILES=`find $userpath -type f -exec du -kx {} \; | sort -nr`
		echo -e "$ALLFILES"
		echo -e "\n Done.\n"
		;; 
	*) 		echo -e "\n Exiting script.\n"
		exit 0
		;;
esac

exit 0
#END