Feed on
Posts
Comments

Quite the messy title, but it really indicates what I am about to demonstrate.

As a sysadmin, there are countless times when I execute a long-running command, and every time I wind up making a statement to myself: “I wish I could get notified when this thing finishes.

About a month ago I had some time on my hands and I finally figured out how to make it work using bash, procps, coreutils and mailx. Essentially any standard Linux distribution will suffice.

Before I begin, I’ve only tested this using Bash 3.2.25 and procps 3.2.7, and coreutils 5.9.7, so your mileage may vary.

To best understand to what I am referring, let’s use an example. I have a find(1) statement which is traversing an enormous filesystem. While I expect the command to take several hours, it is important that I know when it finishes.

find /export/hugearray/ -type f -iname "*.bz2" -exec rm -f {} \;

Now clearly if there are a significant number of files removed, one could make the argument that the result would be noticeable by the increase in available space on the array. While this statement could be true, it doesn’t lend itself to the countless other conditions or situations where disk space may have zero bearing on the outcome of the process.

What I wanted to do was be able to execute a command-line like the following:

command ; notifyme

Where “command” is some long-running task, and “notifyme” is a command which does what it says, notifies me. The big issue was, how could I execute a command on the same line which could step back and see when the previous command finished, and the name of that command? The obvious answer was using bash_builtins(1), “history”, but it was much easier said than done.

It is easy to craft a command that notifies you when the previous command finishes, but it is another thing to get the full argv of the previous command.

Get on with it, how did you solve this?

Alright alright.

I started with “history”. Using “history 1″ we can get the most recently executed command:

[evan@nidhoggr ~]$ ls &>/dev/null ; history 1
 1022  ls &>/dev/null ; history 1

Okay, we’ve obtained the target line, but how do we ditch the history number, and pull off everything including the semi-colon on?

Let’s start by trimming off the history number. While we could use awk or sed for this, we know that there are exactly 8 bytes of padding in front of each history command. I used cut(1) to achieve this.

[evan@nidhoggr ~]$ ls &>/dev/null ; history 1 | cut -b 8-
ls &>/dev/null ; history 1 | cut -b 8-

Now, how do we trim off everything from the LAST semi-colon on, and preserve the original command? It was at this point where I decided to function-ize this process as bash has very convenient string manipulation syntax.

Here is the above command-line functionized so far:

function notify {
  str1="`history 1 | cut -b 8-`"
  echo ${str1}
}
[evan@nidhoggr ~]$ (ls ; ls ; ls) &>/dev/null ; notify
(ls ; ls ; ls) &>/dev/null ; notify

Now we need to tease off the last semi-colon and everything after it, thankfully can do this in bash, by using “%;*” appended on to our string.

function notify {
  str1="`history 1 | cut -b 8-`"
  str2="${str1%;*}"
  echo ${str2}
}
[evan@nidhoggr ~]$ (ls ; ls ; ls) &>/dev/null ; demo
(ls ; ls ; ls) &>/dev/null

At this point we have the meat finished, and now all we need to do is send the output somewhere:

function notify {
  mail="1234567890@txt.att.net franken@berries.com"
  str1="`history 1 | cut -b 8-`"
  str2="${str1%;*}"
  echo ${str2} | mail -s CMD_FINISH ${mail}
}

And there we have it. We define to where to send the mail, first being an SMS to Email gateway, and the other to a local address. We use “CMD_FINISH” in the subject to make the SMS and Email mind-bendingly obvious, with the finished command residing in the body.

Just append this stanza into your ~/.bashrc and you’re good to go.

# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
 . /etc/bashrc
fi

# User specific aliases and functions

function notify {
  mail="1234567890@txt.att.net franken@berries.com"
  str1="`history 1 | cut -b 8-`"
  str2="${str1%;*}"
  echo ${str2} | mail -s CMD_FINISH ${mail}
}

Usage is how you would expect:

[evan@nidhoggr ~]$ ls &>/dev/null ; notify
[evan@nidhoggr ~]$

It is important to point out that bash aliases cannot accept arguments. In order to pass one variable to another in bash, you must use a function. We see this in the bash(1) man page.

There  is no mechanism for using arguments in the replacement text.  If  arguments
are  needed,  a shell  function  should  be  used ...

I hope this post serves other people well. Finally spending the time and figuring this out has really made my life easier.

Something I have been trying to come across out in the internet was a decent, long-term, historical graph of the EUR/USD exchange rate. Being fed up with countless crappy sites and their HTML tables, I decided to pull every last datapoint I could find and create a google widget for your viewing pleasure. One annoying bit about the widget is that the rates were rounded off to 2 decimal places, not 4 like I originally had them. I’ll see if I can correct this issue as it does make a sizable difference. From what I can tell, it appears that the google finance widget for spreadsheets explicitly rounds off all numbers to two decimal points. Ugh.

Please bear in mind that this graph does NOT update automatically like the google finance widget. This data is static from about Dec 1998 through Dec 28 2009.

This graph shows how many EUROS will buy 1 USD.

Jim Grant of Grant’s Index Observer on CNBC corroborates the inevitability of inflation and in my words, “hyperinflation”. He uses the phrase, “wild and wooly.” Jim Grant is right on target.


Remember how a while back I told you all about why my car was better than yours? Well, apart from being totally unnecessarily smug about it I have some more PR to back up my claim.

This latest video just warms the cockles of my heart.

I said I wouldn’t be back for more, but what I am about to say is so vitally important to the safety, health, and survival of the American people that I couldn’t stay quiet any longer.

Hyperinflation is coming to the US thanks to Federal Reserve System Chairman Ben Shalom Bernanke, US Secretary of the Treasury Timothy Franz Geithner, and current US President Barack Hussein Obama II.

bernanke_ben

President_Official_Portrait_HiRes225px-Timothy_Geithner_official_portrait

“That’s crazy talk, the US isn’t susceptible to hyperinflation. Hyperinflation is for countries like Zimbabwe.”

Really..? Says who? Ben Bernanke has a Ph.D. in Economics from MIT and yet he was either completely oblivious to the housing collapse, or he didn’t want to put the country into a state of panic. Regardless, he was wrong again, and again, and again.

As one mistake has led to another, the economy of the US has begun to melt down.

At the end of 2008, and the beginning of 2009, US government was presented with two choices to help correct the direction of the economy. One option was to allow the too-big-to-fails to fail on their own merit and allow free-market capitalism to run its course, the other option was to inject tax-payer money into the economy and large financial institutions to prop them up as it were, due to the perceived enormous negative impact of their failure.

Both of these two options are uncomfortable for everyone and both of these two options result in countless people losing their job. Unfortunately this administration chose the latter as opposed to the former, resulting in the injection of $14 trillion dollars into the world economy.

On December 3rd, 2009 during Ben Bernanke’s Confirmation hearing, Senator Jim Bunning, R-Kentucky gave a very good recap and opinion of Ben’s job as Fed Chairman.

The combination of printing this amount of cash under a Fractional-reserve banking system is a recipe for disaster.

Lastly, and most importantly to this post, the end result is Hyperinflation. Watch the following three videos to get a good understand of exactly what is coming in the next few years for the US. While I realize there may be some commentary by individuals which with you may or may not take personal issue suspend your opinion and just watch.

Part 1

Part 2

Part 3

Older Posts »