Scripting From the Command Line

One of the techniques I use to be effective at Unix systems administration is scripting from the command line. If you understand Bourne shell’s for-loops and while statements, it is just one small step from only using them inside scripts to using them on the command line as part of an ad hoc mini-script. It makes sense, does it not? We use shells for both scripting and command line interaction all the time, and if you do both a lot you should notice that they use the same syntax.

Note that I use the Z Shell (zsh), which is a Bourne compatible shell. These examples should also work in the Bourne shell (sh), the Kornshell (ksh), and the Bourne Again shell (bash). They will not work in the C Shell (csh) or the Tenex C Shell (tcsh). Those shells use a different syntax to accomplish the same thing.

If you want to run a program on one remote computer, you can with ssh like so:

workstation% ssh server-01 /usr/local/bin/locate ruby

Now you want to run the same thing on ten hosts (or twenty-five, or perhaps hundreds). You could start by listing them all in a for-loop (note that the ellipses below are not literal—substitute those with the actual system names):

workstation% for M in server-01 server-02 ... server-10; do
workstation for% ssh $M /usr/local/bin/locate ruby
workstation for% done

And there you go, and all done from the command line! You can build things up even higher. Now let us say you put your hosts into a file called HOSTLIST:

workstation% for M in `cat HOSTLIST`; do
workstation for% ssh $M /usr/local/bin/locate ruby
workstation for% done

You can add more logic in the middle of your loop. This mini-script generates a list of systems that do not have their Ruby installed at a particular location:

workstation% for M in `cat HOSTLIST`; do
workstation for% LOCATION=`ssh $M /usr/local/bin/locate ruby`
workstation for% if [ $LOCATION != /usr/local/bin/ruby ]; then
workstation for if% echo "$M: Ruby at non-standard location: $LOCATION"
workstation for if% fi
workstation for% done

Somewhere along the line here you might decide to move this script into a file of its own, but that is up to you to decide. Whether or not I do so depends on how likely it is that I will use the ad hoc script again and how long it is. In the example above, how often do you need to check that a particular program is at a particular path? For me it is not very often, so I end up doing it with this kind of mini-script. Perhaps you are always checking paths as part of regular audits, though, and thus would move the script to its own file to make it available for repeated use. You will figure out the right thing to do in your environment. 😉

Method Aliasing and Aspect-Oriented Programming

One of the things that I have recently played with in Ruby is a sort of aspect-oriented programming. I say “sort of” because Ruby is not really an aspect-oriented language out of the box, but with some inconvenient constructs one can approach problems in this manner, using this mindset. I touched this because I am writing extensions to another program already written in this style. I think a lot of Rubyists do this when modularizing their code. What I saw was that one of the classes I needed to modify was modularized into several components:

class Shape
  module CurvySides
    # ... code supporting curvy sides here ...
  end

  module StraightSides
    # ... code supporting straight sides here ...
  end

  include CurvySides, StraightSides
end

Actually, each concern was in a separate file:

require 'shape/curvy_sides'
require 'shape/straight_sides'

class Shape
  include CurvySides, StraightSides
end

Read the rest of this entry »

Security Risk Assessments

Risk assessments are one of the main tasks I am faced with day-to-day with my security work. Most of the time it comes in as a request to “approve” some architecture. In my head, this is basically a security risk assessment where I also getting to decide for the business that the benefit of allowing the architecture is greater than the associated risk. Usually I can just make a quick judgment call and give a “thumbs up” or help the user with tweaking his architecture to produce an acceptably secure solution, but sometimes I have to write out my reasoning for disapproving something. Then the mangers that end up deciding that we move forward on the given architecture have adequate knowledge of the risk.

Recently I had started using Microsoft’s DREAD framework for performing written security risk assessments. I liked it because at the end of my assessment I can deliver a number to my management. Low numbers are good, and high numbers are bad. For about two months and about six written assessments (not many, I know) I was very happy with the numbers the DREAD framework was giving me when I used it. I felt the numbers were adequately expressing the risk to the organization.

Then, earlier this month, I did one more for a project that I felt held insignificant risk to the organization, but I did not give it the usual rubber stamp approval because the project ignored some good practices that I wanted to insist upon (when I say ignored I mean thumbed their nose up at me when I told them they should do it). I thought that if they were going to go against my recommendations that we should all have an accurate risk assessment of what that meant. However, the resulting score out of DREAD was high, and as I said before, does not accurately represent the true risk of this project. The reason DREAD failed here was that its score is the result of an addition instead of a multiplication of the various risk factors (most models I have seen use multiplication), so one low score means little in the face of some other high factors.

Read the rest of this entry »

From Vim to TextMate

Yesterday I switched from using Vim for all my code editing to TextMate. It is Mac only and costs €39 when I decide to register, but I really like how much easier it is to switch between more than two files and how it auto-terminates parentheses, logical statements, and HTML tags. This latter behavior should be possible in Vim, but I had never found a plug-in or information on how.

I also looked at Eclipse, but it has not grown on me nearly as fast. In fact, at the risk of sounding like an Eclipse basher, I must say the interface is non-intuitive and the help files address every subject under the sun and the moon except how to make Eclipse useful. I am sure that under all that non-intuitiveness and bad documentation is an excellent product, but I will not invest that much time to find it (yet) with TextMate already paying me back handsomely for only ten minutes of my time to install it and configure my preferences. One might say this is the difference between a text editor and a full IDE—that may be true to some degree—but I think it is also the difference between a good user interface and just an interface.

I gave NetBeans a test drive as well. Let us just say that Eclipse, at least, did not get moved to my Trash and has no plans of visiting, either. I may not have learned to like Eclipse, but I also still see value in learning more about it. In a way I hope I am wrong about NetBeans, but it gets to wait a while before getting another shot.

So why did I do all this? To write code faster! I love Vim and the vi interface, but I like trying new things. I might switch back after a few months if I can find out how to obtain what I like about TextMate in Vim. Being rather extendable, Vim is capable of much more than I have demanded of it. However, the main point is that it is important to me to try out new things periodically, or else I will never learn of the coolest new things (like I did when I learned Ruby in 2001). I also periodically revisit things, such as Emacs about 18 months ago. I did not switch, but getting reacquainted with it eight years after my last time seriously using it was fun.

I like to encourage everyone to pick up new things every once in a while. Do not settle in a groove and stay there for the rest of your life. Mix things up a little! If you do not like your new adventure after a few days or weeks, you can always switch back! It is fun, and may be profitable, too. Of course, if you are the kind of person reading this, you probably already do this. Carry on!

Debugging Connectivity Problems

The Application is down! No, wait! Our Unix administrators just checked the server and it is running. They swear by it, and say it is the network team’s equipment dropping packets. The network team checks their systems and swear they are passing the traffic, and it must be an application configuration issue. The application folks, who originally reported the problem, throw up their hands and go back to the systems administrators for more help. Before long the teams are in a quagmire of blame and nothing is getting done towards fixing the issue. How can we step around that? What should we be doing to fix the Application? If you are the systems administrator then let us try and verify what the network guys are saying. If they really are dropping packets then let us bring some confirmation of that to the table.

Firstly, check your routing tables and your basic network configuration. More than one Unix administrator on a rampage of righteous indignation against their network team has found himself swallowing his own pride when it was discovered that he had errors in his routing table. So check your IP address, your netmask, and your default router first. All good? Now check if you need or have any other routes in your routing table. All good here, too? Excellent! If you are new to Unix and need help finding this information, read the man pages for ifconfig and netstat to get started. I would love to give some examples but it differs very much from Unix variant to Unix variant. In general, though, use “netstat -nr” for viewing the routing table and “ifconfig -a” for seeing all of the network interface configuration information.

Now that you IP configuration is confirmed, let us move on to the connection in question. Firstly, you have to identify the port and protocol of the connection. If you are running a standard protocol, such as HTTP, then you can likely assume port 80, but perhaps you do not know? We have a couple options.

Read the rest of this entry »