Wednesday, January 9, 2013

Linux tip: Using the read command

http://www.itworld.com/development/333494/linux-tip-using-read-command


This content is excerpted from the new 3rd Ed. of 'A Practical Guide to Linux: Commands, Editors, and Shell Programming', authored by Mark Sobell, ISBN 013308504X, published by Pearson/Prentice Hall Professional, Sept. 2012, Copyright 2013 Mark G. Sobell. For more info please visit www.sobell.com or the publisher site, www.informit.com

exclamation point
flickr/kevin dooley

read: Accepts User Input

A common use for user-created variables is storing information that a user enters in response to a prompt. Using read, scripts can accept input from the user and store that input in variables. The read builtin reads one line from standard input and assigns the words on the line to one or more variables:
[Five Linux predictions for 2013 and 14 of the most useful Linux websites]

$ cat read1
echo -n "Go ahead: "
read firstline
echo "You entered: $firstline"
$ ./read1
Go ahead: This is a line.
You entered: This is a line.

The first line of the read1 script uses echo to prompt for a line of text. The –n option suppresses the following NEWLINE, allowing you to enter a line of text on the same line as the prompt. The second line reads the text into the variable firstline. The third line verifies the action of read by displaying the value of firstline.
The –p (prompt) option causes read to send to standard error the argument that follows it; read does not terminate this prompt with a NEWLINE. This feature allows you to both prompt for and read the input from the user on one line:

$ cat read1a
read -p "Go ahead: " firstline
echo "You entered: $firstline"
$ ./read1a
Go ahead: My line.
You entered: My line.

The variable in the preceding examples is quoted (along with the text string) because you, as the script writer, cannot anticipate which characters the user might enter in response to the prompt. Consider what would happen if the variable were not quoted and the user entered * in response to the prompt:


$ cat read1_no_quote

read -p "Go ahead: " firstline
echo You entered: $firstline
$ ./read1_no_quote
Go ahead: *
You entered: read1 read1_no_quote script.1
$ ls
read1     read1_no_quote     script.1

The ls command lists the same words as the script, demonstrating that the shell expands the asterisk into a list of files in the working directory. When the variable $firstline is surrounded by double quotation marks, the shell does not expand the asterisk. Thus the read1 script behaves correctly:

$ ./read1
Go ahead: *
You entered: *

REPLY
When you do not specify a variable to receive read's input, bash puts the input into the variable named REPLY. The following read1b script performs the same task as read1:

$ cat read1b
read -p "Go ahead: "
echo "You entered: $REPLY"

The read2 script prompts for a command line, reads the user's response, and assigns it to the variable cmd. The script then attempts to execute the command line that results from the expansion of the cmd variable:

$ cat read2
read -p "Enter a command: " cmd
$cmd
echo "Thanks"

In the following example, read2 reads a command line that calls the echo builtin. The shell executes the command and then displays Thanks. Next read2 reads a command line that executes the who utility:

$ ./read2
Enter a command: echo Please display this message.
Please display this message.
Thanks
$ ./read2
Enter a command: who
max     pts/4      2013-06-17 07:50 (:0.0)
sam     pts/12     2013-06-17 11:54 (guava)
Thanks

If cmd does not expand into a valid command line, the shell issues an error message:

$ ./read2
Enter a command: xxx
./read2: line 2: xxx: command not found
Thanks

 The read3 script reads values into three variables. The read builtin assigns one word (a sequence of nonblank characters) to each variable:

$ cat read3
read -p "Enter something: " word1 word2 word3
echo "Word 1 is: $word1"
echo "Word 2 is: $word2"
echo "Word 3 is: $word3"
$ ./read3
Enter something: this is something
Word 1 is: this
Word 2 is: is
Word 3 is: something

When you enter more words than read has variables, read assigns one word to each variable, assigning all leftover words to the last variable. Both read1 and read2 assigned the first word and all leftover words to the one variable the scripts each had to work with. In the following example, read assigns five words to three variables: It assigns the first word to the first variable, the second word to the second variable, and the third through fifth words to the third variable.

$ ./read3
Enter something: this is something else, really.
Word 1 is: this
Word 2 is: is
Word 3 is: something else, really.


Table 10-4 lists some of the options supported by the read builtin.

Table 10-4 read options

Option Function
–a aname (array) Assigns each word of input to an element of array aname.
–d delim (delimiter) Uses delim to terminate the input instead of NEWLINE.
–e (Readline) If input is coming from a keyboard, uses the Readline Library to get input.
–n num (number of characters) Reads num characters and returns. As soon as the user types num characters, read returns; there is no need to press RETURN.
–p prompt (prompt) Displays prompt on standard error without a terminating NEWLINE
before reading input. Displays prompt only when input comes from the
keyboard.
–s (silent) Does not echo characters.
–un (file descriptor) Uses the integer n as the file descriptor that read takes its input from. Thus read –u4 arg1 arg2
is equivalent to
read arg1 arg2 <&4


How to extend Nagios for custom monitoring

http://www.openlogic.com/wazi/bid/256126/how-to-extend-nagios-for-custom-monitoring


The powerful Nagios network monitoring platform lets you supercharge its capabilities with a host of available plugins. If you can't find a plugin to do just what you need, you can easily write your own – here's how.
Nagios plugins can be written in any programming language supported on the platform that's running Nagios. Bash is a popular choice for writing Nagios plugins because it is both powerful and simple.
Every valid Nagios check from a plugin has to produce a numeric exit status. Possible statuses are:
  • 0 – Everything is OK and the check completed successfully.
  • 1 – The resource is in warning state. Something is not quite right.
  • 2 – The resource is in critical state. A host may be down or a service not running.
  • 3 – Unknown state, which does not necessarily indicate a problem, but rather shows that the check cannot give a clear, unambiguous status.
A plugin can also print a text message. By default, this message is shown in the Nagios web interface and in Nagios mail alerts. Even though messages are not a requirement, you usually find them in available plugins because they tell users what is wrong without forcing them to consult documentation.
A simple Nagios plugin written in Bash looks like this. This example plugin checks a specified file:
#!/bin/bash

#assign the first argument ($1) as the filename
filename=$1

#first check if the file exists. this is the first and most basic check with which you should begin
if [ ! -e $filename ]; then
    echo "CRITICAL status - file $filename doesn't exist"
    exit 2 #returns critical status because your worst scenario is that the file doesn't even exist

#if the previous condition passes (file exists) then next check if it is readable    
elif [ ! -r $filename ]; then
    echo "WARNING status - file $filename is not readable."
    exit 1 #returns warning status because this state is better than having no file at all

#if the previous condition passes, check if it is a regular file and not a directory or device file
elif [ ! -f $filename ]; then
    echo "UNKNOWN status - file $filename is not a file."
    exit 3 #returns unknown status
    
#if all of the above checks pass then it's ok
else
    echo "OK status - file is OK"
    exit 0 #Return OK status
fi
Comments (which start with # in Bash) explain the code; if you need more clarification or want to learn more about Bash's file test operators, check the documentation.
Even though this example is simple, it is a good illustration of how to implement Nagios plugin logic. Always start by probing for the worst possible scenarios. Only when all checks pass should the script exit with status OK. Make sure to specify the clarifying message before exiting.

Using the plugin

By default, all Nagios plugins are stored in the directory defined in the $USER1 macro, defined in the file /etc/nagios/private/resource.cfg. In a typical Nagios installation from EPEL's repository, $USER1 is defined to /usr/lib/nagios/plugins. The first thing you should do with your plugin is to copy it to the directory defined in $USER1 macro. Usually plugins are owned by root and have permissions of 755; Nagios works under the user nagios, which belongs to the nagios group, so the script requires read and execute permissions for other groups.
Once you place a script in the /usr/lib/nagios/plugins directory you have to define it as a Nagios command within the file /etc/nagios/objects/commands.cfg. Let's say you named your script check_file.sh; add the following command definition:
# our custom file check command
define command{
        command_name    check_file
        command_line    $USER1$/check_file.sh $ARG1$
        }
That should be pretty clear. The variable $ARG1$ stands for the first argument passed to the Nagios command, which in our case should be the name of the file. If you want to pass more arguments, use $ARG2$ for the second argument, $ARG3$ for the third, and so on.
To start using your plugin, define it as a service in your nagios configuration(services.cfg for example):
define service{
        use                             local-service
        host_name                       localhost
        service_description             Check the file /etc/passwd
        check_command                   check_file!/etc/passwd
        }
The above service is defined for localhost (host_name localhost) and uses the template (see the documentation on object inheritance for templates and how they work) for local-service (use local-service). The most important part is the check_command directive. It specifies the command check_file, followed by an exclamation point as a separator, followed by a file name as argument. If your plugin has more than one argument you can separate them with additional exclamation points.

Running Nagios plugins remotely

One obvious flaw of the example check_file plugin is that it works locally, which means you cannot check a file on a remote server. You can resolve this problem in a number of ways.
The first approach would be to use the ssh command to execute the script remotely. This requires you to copy the script to a remote server and make use of ssh's ability to run remote commands. It also requires you to set up passwordless key login for the Nagios server and its nagios user. If you are not sure how to do this, check this article for all the details.
The benefit of this first approach is that you have all the power and flexibility of running commands locally for the monitored server. The drawback is that the Nagios server has to be able to log in passwordless with a key to the remote server. This is a security issue and not recommended for sensitive environments.
A second and more secure approach is to use the SNMP extend feature. This requires that you have the net-snmp package (for CentOS) installed and configured on the remote server.
To use the SNMP extend command, first copy the check_file.sh script to the remote server. You can place it in the directory /usr/bin/, for example.
Next, add the configuration directive extend check_passwd_file /usr/bin/check_file.sh /etc/passwd to the file /etc/snmp/snmpd.conf on the remote server. The syntax is extend some_alias command argument. Here comes the main inconvenience of this method – you have to define an alias for each separate check, which in our case means an alias for each separate file we want to test, because you cannot send arguments over SNMP.
Any changes in the file /etc/snmp/snmpd.conf require you to reload the snmpd service with the command service snmpd reload (for CentOS). After that you can test the new check with the snmpget command, as in snmpget -v2c -c public -OvQ 10.0.0.2 NET-SNMP-EXTEND-MIB::nsExtendOutputFull.\"check_passwd_file\". This example snmpget command queries the server 10.0.0.2 over SNMP version 2c with the "public" community string. The object identifier (OID) for your custom SNMP extended commands is NET-SNMP-EXTEND-MIB::nsExtendOutputFull.\"some_alias\".
Unfortunately the above command cannot be implemented directly in Nagios. If snmpget works properly and can connect to the remote host, it will always return status 0, indicating everything is OK, because the program snmpget itself exits without an error. Thus even if a file doesn't exist, the check script will return status 0, though it will print the correct message that the file is not there.
You can address this problem by taking advantage of a special plugin for Nagios called check_snmp_extend.sh. This plugin takes the first word from a status message and sets the status according to it. It was in anticipation of using this plugin that we set the messages in our example script check_file.sh to start with OK, CRITICAL, WARNING, and UNKNOWN.
To start using the check_snmp_extend.sh plugin, first download it, then place it in the directory /usr/lib/nagios/plugins ($USER1 macro) on the Nagios server. On CentOS you have to edit the script check_snmp_extend.sh and replace /usr/local/nagios/libexec/utils.sh with /usr/lib/nagios/plugins/utils.sh, which is the correct path for the utils.sh script.
After that you can use check_snmp_extend.sh just like any other plugin. First, define it as a command:
define command{
 command_name check_snmp_extend
 command_line $USER1$/check_snmp_extend.sh $HOSTADDRESS$ $ARG1$
}
After that define a service:
define service{
 use                 generic-service
 host_name         somehost.example.org
 service_description Check For /etc/passwd
 check_command  check_snmp_extend!check_passwd_file
}
Using SNMP's extend option is as secure as your SNMP configuration is. This approach requires minimal modification on remote hosts and ensures a standard setup conforming to best security practices. You can find other Nagios plugins for similar purposes, such as nrpe, but they require the remote installation of additional services, which is not always a good idea from a security and compatibility point of view.
As you can see, it's easy to extend Nagios with custom-written plugins. The fact that Nagios allows such extension is one of the reasons many administrators prefer it over other monitoring solutions.

Linux In The Cloud: Windows Azure vs. Amazon Web Services

http://tuts.pinehead.tv/2013/01/07/linux-in-the-cloud-windows-azure-vs-amazon-web-services


Until recently, the most viable cloud option for Linux virtual servers has been Amazon Web Services. But in mid 2012, Microsoft launched Linux Virtual Servers on Windows Azure. If you don’t know already, Windows Azure is a cloud platform for hosting back-end content for apps and traditional Windows Server, SQL Server, and now Linux and other open source database servers. Microsoft has come a long way with its support for open source and Linux. Given that, I set out on a mission to review and compare these services to Amazon. I’ll be honest up-front–when I set out on this mission I was completely biased towards Amazon, and I was surprised by what I found.

What I’m Comparing

I think it’s important to detail what services I’m comparing, as of now Amazon Web Servers has many other cloud services that Windows Azure does not. My primary focus will be on Linux virtual servers, the hardware specs, Azure interface, and other aspects of running Linux Virtual Severs in the cloud.

Where Azure Beats Amazon

Microsoft is clearly trying to mimic the new “m” (metro) design that comes with the new Windows 8. From a usability standpoint, parts of it are very slick. The entire interface is very “ajaxy”–from building a new server to viewing options, it loads lightning fast and presents the data in column fashion. I can’t be more thrilled with the quick launch menu and how fast you can launch a basic Linux server.
It takes me three clicks to build a Linux VPS assuming I’m selecting one of the “quick launch” images, which include CentOS, Suse, and Ubuntu servers. I guess I’m lucky I’m a CentOS guy.
Screen Shot 2013-01-03 at 10.38.51 PM
Quick Launch
When I think Linux VPS in the cloud, I think of starting on the smallest possible server I can and then scaling when capacity is required. The Azure VPS “micro” server comes with more memory and a significant more disk space than Amazon Web Services “micro” instance. The root partitions are also larger in size by default. However, Azure does not allow you to resize your partition like Amazon does.

Options For Security

When you build your first Linux server on Amazon, you’re required to use a .pem key file for security. The file is intended to give you root access to your servers, securely  However, if you need to build a server fast, on the fly, and don’t have time to run the putty ppk conversion or have a UNIX machine handy, then you’re just out of luck. That first step towards getting started on Amazon has tripped up many first time Linux users as they dive into the cloud. However, Microsoft gives you two options while building your first image. You can either chose to use a security key file or you can use a root username and password. The username and password method is less secure but if you have other plans for security for your network and servers, bypassing the mandatory pem file will save you a lot of time and hassle in the end. Bottom line, secure or not secure, I love that Microsoft gives you the option.

Basic Benchmark Test

I performed some basic benchmark tests on an Amazon “micro” instance and an Azure “extra small” instance. What I found from random “time” benchmarking tests is the Amazon micro instance and Windows Azure are pretty consistent even through those basic benchmark tests. A lot of the differences are due to Azure by default providing larger disk space on the system which causes increased time when performing disk commands.

Here Is Where Azure Can Improve

Charging for stopped instances is a deal breaker. If you build a virtual server, whether the server is running or not running, you are charged for CPU/hours. Amazon does not charge for instances that are stopped but only for running instances. I have come to find it very advantageous to be able to have stopped servers that I can go back to months down the road and work on. Having to pay for those on Azure would cost too much.
Screen Shot 2013-01-03 at 9.27.43 PM
Azure Charges For Stopped Instances
I can’t control the instance by right clicking on the instance. After working with Azure for a decent time period I was consistently annoyed that in order to stop, start or delete my instance I had to first click on the instance name then browse the bottom of my screen for navigation options. Working with Amazon web services or VMware for so long, it’s become intuitive for me to find the options for my instance by a right navigation menu. Of course, I still prefer a start menu as well…
Screen Shot 2013-01-03 at 9.55.43 PM
Bottom Navigation And Confirmation
With simplicity comes complexity and the Azure interface has some. When working on Amazon, I’m presented with a dashboard for my servers and everything I could possible want to do including configuring a firewall, load balancing, changing IP addresses, configuring volumes and more. However, while Azure proves they have a simple user interface when it comes to launching servers, managing complex operations in the interface seems elusive. In fact, it seems downright impossible. For instance, if there is a firewall or load balancing management, I can’t find it. I’m not saying they don’t exist–I’m saying that I was unable to find those options from my “portal.” If they don’t exist, they are must haves for running servers in the cloud and Azure needs them. If they do either it’s not available under my “free tier” or they need to be made more readily available and intuitive for the user.
Screen Shot 2013-01-03 at 10.45.56 PM
This is the detailed view of the instance where I was hoping to find options such as changing the static IP address on the server. However, those options seemed elusive still.

Conclusion

Out of the box I’m impressed with what Microsoft has created at Azure. They’ve created a simple to use basic environment, which makes it extremely simple to build Linux servers in the cloud. A little leeway for Azure’s shortcomings can be given based on the age of the service (for Linux) but Azure will be a great cloud solution whether you’re hosting small scale web apps or large apps that need scaling.