Posted by hank,
Sun Mar 30 21:16:00 UTC 2008
Today, I decided I wanted a network service that propagated variables and aliases to every login shell that subscribed to it. This is dangerous on a large scale, but perfectly acceptable on my small home network where everyone trusts everyone else.
First, I got Camping installed, bringing back fond memories of Ruby development. I then copied off the blog example, and created TreeHugger, a 427 line script that provides a web interface to edit the variables, and a plain text output for the shells to source.
This script, when run, allows some simple MVC actions to an sqlite3 database.

As you can see, I have some aliases here I want to send to all the subscribing hosts. Eventually, I want to add some detection functionality to the database (mostly reverse DNS lookups for host rule referencing). I just have to access /out to get my desired output:
# Treehugger Configuration
# Aliases
alias ai='sudo apt-get install'
alias aup='sudo apt-get update'
alias aug='sudo apt-get upgrade'
# Environment Variables
Now, to get this into bash. I looked into making the date command spit out pretty unique timestamps. Turns out you can do this with the nanoseconds format:
$ date +%s%N
1206926780157462141
I made it so wget saves the treehugger config to a tempfile using the somewhat random seed above as a filename suffix, and then I have my shell source it:
FILENAME=/tmp/treehugger-`date +%s%N`; 2>/dev/null wget -O $FILENAME http://rofl.who/treehugger/out && source $FILENAME && rm $FILENAME
And now I have nice aliases on my laptop served up from my desktop as fresh as the shell:
hank@davros:~$ alias
alias ai='sudo apt-get install'
alias aug='sudo apt-get upgrade'
alias aup='sudo apt-get update'
alias ls='ls --color=auto'
Tags: bash
Posted by hank,
Sat Dec 08 13:09:00 UTC 2007
Code
Here’s a quick one-liner using some UNIX utilities and Perl to construct some nice averages from CSV data:
for i in `seq 2 20`; do cat crim_rate_2005_by_state.csv | cut -d , -f $i | perl -e '$c=$d=0;$e;while(<>){if(/^\d/){$c+=$_;$d+=1}else{s/\s{2,}/ /g;s/"//g;chomp($e=$_);}} print $e, ": ", $c/$d, "\n"'; done
And now, the spaced out version:
#!/bin/bash
for i in `seq 2 20`; do
cat crim_rate_2005_by_state.csv | \
cut -d , -f $i | \
perl -e '$c=$d=0;
$e;
while(<>){
if(/^\d/){
$c+=$_;
$d+=1
} else {
s/\s{2,}/ /g;
s/"//g;
chomp($e=$_);
}
}
print $e, ": ", $c/$d, "\n"';
done
Output
- Population: 5775431.88461538
- Violent crime rate: 418.930769230769
- Murder/manslaughter rate: 5.59038461538462
- Forcible rape rate: 33.1634615384615
- Robbery rate: 114.455769230769
- Assault rate: 265.728846153846
- Property crime rate: 3339.50961538462
- Burglary rate: 685.671153846154
- Larceny/theft rate: 2273.43269230769
- Motor vehicle theft rate: 380.417307692308
- Violent crime: 26928.3461538462
- Murder and nonnegligent manslaughter: 335.730769230769
- Forcible rape: 1809.67307692308
- Robbery: 8128.30769230769
- Aggravated assault: 16654.6346153846
- Property crime: 196569.711538462
- Burglary: 41756.0961538462
- Larceny-theft: 130880.442307692
- Motor vehicle theft: 23933.1730769231
So, now we have our averages. More work to be done. The data file used is available here:
Tags: bash
Posted by hank,
Thu Jul 19 22:45:00 UTC 2007
This awesome page told me about the <<< operator in bash. It rocks. It also told me the best way to set an initial login password:
umask u=rw,go=
openssl rand -base64 6 | tee -a PasswordFile | passwd –stdin joe
chage -d 0 joe
Also, there’s ssh-copy-id:
Usage: /usr/bin/ssh-copy-id [-i [identity_file]] [user@]machine
Tags: bash
Posted by hank,
Sat Jul 14 20:17:00 UTC 2007
I use GNU Screen. A lot. I found an article linked from DIgg today that showed me how to use a setting called hardstatus to set the little bar at the bottom to my liking. I decided to mess around with it a bit, and I ended up with this:

It shows my hostname, IP, uptime, screen window number and name, date and time, and load averages. Pretty cool, huh?
This is how you do it:
- First, create a
.screenrc file and dump this in there:
hardstatus alwayslastline
backtick 1 60 60 /home/hank/.screen_hardstatus
hardstatus string "%{Gk}%H: %{+s y}%1` | %=%n: %t%= | %m/%d %c | %{+b}%l"
- Now, see the line that starts with backtick? That tells screen what program to run for assigning output to
%1` in the hardstatus string. Let’s make the .screen_hardstatus file as well (make it in your own home directory).
#!/bin/bash
# Script to get run by hardstatus in screen.
# Prints customized single-line system stats
IP=`ifconfig eth0 | grep Mask | cut -d: -f2 | cut -d " " -f1`
UPTIME=`perl -pe 's/^(\d+).*/sprintf("%d", ($1\/(24*3600)))." days"/e' /proc/uptime`
echo -n "$IP | Up: $UPTIME"
I cheated and used perl, but all of this could safely be converted to sed/awk easily. All this does is print my raw dotted quad IP address, a pipe, and then the current uptime in days rounded down.
- Now, just run
screen. You should see something similar to the first picture. I used this page a lot to customize the colors, etc.
Tags: bash
Posted by hank,
Sat May 19 04:06:00 UTC 2007
I thought this was pretty cool:
for i in `seq -f "%03g" 1 100`; do wget http://www.gozerog.com/images/Hawking_$i.jpg; done
We were trying to do this the other night using bash, but to no avail since the square brackets only work for local file path expansion. I should have remembered seq. Also, this example shows how to 0-pad a series using seq and bash, noted by the *-f* option. Three cheers for seq!
Tags: bash
Posted by hank,
Mon Mar 26 14:40:00 UTC 2007
I often find myself going to find scripts I’ve written that I want to edit, but I decided today I’d make things easier on myself:
hank@rura-penthe ~ $ cat bin/vimwhich
#!/bin/bash
vim `which $1`
All this does is shorten vim `which myscript` to vimwhich myscript. Helpful for just a couple lines of code.
Tags: bash