Mac OS X What is my IP Address?!

I’ve asked this question a lot. What is my IP address? This can be for any number of reasons. There are a number of ways that this can be done, but I was looking for a way to do this on the command line. Well… it didn’t turn out to be as simple as I had hoped.

ipaddr

The primary tool is ifconfig. However, that spits out way more information then I wanted. So a little bit of reading, some regular expressions, and I created the following script. Note that en1 is my wireless port because I am always on my wireless:

#!/bin/sh
ifconfig en1 | awk '$2~/[0-9]+./{print$2}'

Update: I found a better solution:

#!/bin/sh
# Update: Even Better!
ipconfig getifaddr en1

Here is some usage and me checking that it actually makes sense:

ipaddr usage

ipaddr2

I’m paranoid… so let me double check at whatismyip.com. “What!?” That didn’t make sense. Or did it? A few minutes later, after running a traceroute and following the hops I noticed that sure enough the Frontier Wireless provider in this public CafĂ© was using that IP address. So I wrote a quick curl script to pull whatismyip’s opinion and quite craftily they must have planned for this:

whatismyip suggestion

Cool. That makes my job even simpler. The response is simply my ip address string. Add an echo to provide a newline and I’ve got a useful script.

#!/bin/sh
curl --silent www.whatismyip.com/automation/n09230945.asp
echo

Hopefully these two scripts can help save someone a few minutes. ipaddr to see what my machine’s ip address is and ipaddr2 to see through what ip address my computer is reaching the outer world. Cheers.

Ruby Process Controller – psgrep

Every once in a while a process will freeze and will be too stubborn to die when I try to “Quit” it. For those stubborn processes I tend to use the terminal to `kill` it. For a while I had been using a simple Perl script for searching through processes. The script would find me the processids and I could then kill it, using whatever power I need.

I found that it was taking far too long for me to do the search, and then carefully type out the process id, and hope I got the right one. I discovered killall, but the problem is that sometimes I don’t want to kill “all” of the processes with that name. So, I gave in and wrote up a Ruby script that did what I wanted. Here is psgrep: (Download)

#!/usr/bin/env ruby
# Start Date: Saturday December 6, 2008
# Current Version: 0.9
# Author: Joseph Pecoraro
# Contact: joepeck02@gmail.com
# Decription: Quicker handling of process searching
# and killing.  Never type in a PID again, just regexes!

# -----------
#   Globals
# -----------
kill_mode = false
icase_mode = false
pattern = nil
targets = []
pids = []

# ---------
#   Usage
# ---------
def usage
  puts "usage: #{$0.split(/\//).last} [options] pattern"
  puts "  -k  or --kill   kills all processes"
  puts "  -k# or --kill#  kills the [#] process"
  exit 0
end

# -----------
#   Options
# -----------
if ARGV.size > 1
  ARGV.each do |arg|
    if arg.match(/^-(k|-kill)(\d*)$/)
      kill_mode = true
      targets << $2.to_i unless $2.empty?
    elsif arg.match(/^-(i|-ignore)$/)
      icase_mode = true
    end
  end
  ARGV.delete_if { |e| e.match(/^-/) }
end

# -------------------
#   Remaining Args
# -------------------
if ARGV.size != 1
  usage
end

if icase_mode
  pattern = Regexp.new( ARGV[0], Regexp::IGNORECASE )
else
  pattern = Regexp.new( ARGV[0] )
end

# ----------------------
#   Actual `ps` Output
# ----------------------
lines = %x{ ps -Au#{ENV['USER']} }.split(/\n/)
header = lines.shift

# ----------
#   psgrep
# ----------
puts
puts "     #{header}"
count = 0
lines.each do |line|
  unless line =~ /psgrep/
    if line.match(pattern)
      count += 1
      puts "[#{count}]: #{line}"
      if targets.empty? || targets.member?(count)
        pids << line.strip.split[1]
      end
    end
  end
end

# -------------
#   Kill Mode
# -------------
if kill_mode
  puts
  puts "Killing Processes"
  puts "-----------------"
  pids.each_with_index do |pid, i|
    print targets.empty? ? "[#{i}]:" :  "[#{targets[i]}]:"
    print " Killing #{pid}... "
    STDOUT.flush
    res = %x{ kill #{pid} }
    puts "Dead" if $?.exitstatus.zero?
  end
end

# Always
puts

So there it is. Less then 100 lines of ruby to get a pretty straightforward psgrep/kill program. Here is an example where I have three perl processes running on my machine. One of the is running as root (the userid is 0). I just type “!! –kill” or “[up-arrow] –kill” and it tries to kill them all. Note that the root perl process doesn’t terminate and there is an error message but psgrep continues as best as it can, and kills the two normal perl processes: [Note: I could have done `sudo psgrep perl -k` to kill the root process]

psgrep usage

Here is another good example. I have two python instances that I want to kill but there is another python instance running ExpanDrive in the background. I just ran psgrep and found the two I want to kill are [2] and [3]. Therefore, I can send -k2 and -k3 (or –kill2 and –kill3) to kill only those processes. Here is the result:

psgrep target

Note also that by default psgrep is case-sensitive. To ignore case just add the -i or –ignore switch. So there you have it. Usage is straightforward. Switches can go anywhere on the command line makes it easier to just use your history and tack a switch on the end of your previous command.

Feel free to improve it, it is on GitHub!

SotD – Remove the First N Characters From a Line

I was asked today to remove the first 6 characters from every line in a document. It was known that each line contained at least 6 characters. For me, that means a find a replace. Here is how I did it (in a number of different ways). Can you think of any other ways to do it?

cut -c7-
rr ^.{6}
colrm 1 6
rr s/^.{6}//
sed 's/^.\{6\}//'
perl -pe 's/^.{6}//'
ruby -pe 'sub /^.{6}/,""'
gawk 'BEGIN{FIELDWIDTHS="6 999"}{print$2}'

I was pretty happy with rr taking the prize for least characters. I do want to point out that since rr defaults to multi-line and global replacements the “^” is required. If you wanted to remove the “^” (like you could with sed, perl, and ruby) then you would have to use the “–line” or “-l” and “–notglobal” or “-ng” options. So a single character replaces 7! If you want to grab rr just do:

$ sudo gem install regex_replace

Also, here is a link to gawk – GNU’s awk. This has the very nice FIELDWIDTHS variable, which is extremely useful!

Also keep in mind that the regular expressions above ^.{6} only work because the lines were known to have at least 6 characters. If we didn’t know that we would have had to use something like ^.{0,6} to allow up to 6 characters (and even that could be ^.{1.6} ignoring blank lines which can’t change). So again the requirements for this challenge were important.

Update!

I came across a neat little unix utility I didn’t know about called “cut”. As you can see, the new command tops the list quite handily too. “cut -c 7-” is actually cutting from each line the 7th character onwards (counting starts from 1). In this case once it spits what it cuts out to stdout; so it leaves behind those first 6 characters and therefore accomplishes our goal. In the above list I removed the optional space after “-c” to make it just a tad shorter. Pretty neat.

Then I found “colrm” which is the most straightforward. This one wins in simplicity. No hacks, just straightforward does exactly what you think it does. Very cool.

Double Update!

I figured since quite a bit of my rr usage has an empty string for the second argument, I figured it would be okay to throw that in as the default case. So now there is a third usage for rr, which is great for pipes, that just strips something out. That brings rr back up to a tie for first place. Very cool.

Upcase a File – SotD

I just came up with something fun. Sotd – Script of the Day. Whenever I find/make a good script I will try to include it here, with the tag, and some fun content to work around it. Today’s script is the simple task of converting an entire file to uppercase. To standardize solutions I will say the current file is in.txt and we want the output file to go to out.txt. Here goes…

This simple task came from a question posted on Experts Exchange in the Scripting zone. Specifically Perl, however I putzed around with Perl and couldn’t quickly figure out what my print uc($_); was doing wrong, so I moved on to try my luck with Ruby. One minute without a need to look up any functions and 30 seconds of it not realizing I was still in the irb… and I had my Ruby solution:

> ruby -e "puts File.read('in.txt').upcase" > out.txt
> ruby -ne 'puts $_.upcase' < in.txt > out.txt

Which helped me produce the perl solution:

> perl -ne 'print uc' in.txt > out.txt

But I figured there had to be an easier way. I decided to manipulate tr///, transliterate, to convert lowercase characters to uppercase with the following one-liner piping the input file through tr and redirecting the output:

> cat in.txt | tr a-z A-Z > out.txt

I was pretty happy with it. How would you have done it?

search