Work the Shell - Web Server Tricks with $RANDOM
I just migrated onto a newer, bigger server (read that as “more expensive”, of course, but because my traffic's justifying it, I'm good with the change). To make matters more interesting, I also just bought a new laptop (a MacBook Pro), and between the two migrations, I've been looking through a lot of old directories and bumping into all sorts of scripts I've written in the past few years.
The one I thought would be interesting to explore here is one I wrote for a pal who was involved in a charity and wanted a way to have a single URL bounce people 50/50 to one of two different Web pages—a sort of mini-load balancer, though his application wasn't quite the same.
The core piece of this is the $RANDOM shell variable that's actually kind of magical—each time you reference it, you'll find it's different, even though you aren't actually assigning a new value to it. For example:
$ echo $RANDOM 21960 $ echo $RANDOM 19045 $ echo $RANDOM 2368 $ echo $RANDOM 2425 $ echo $RANDOM 10629
This violates the core user design principles of the shell and even the very definition of variables (which are supposed to be predictable—if you assign the value 37 to it, it still should have that value 200 lines and 17 references later). Other variables change value based on what you're doing, without you actually assigning it a new value, like $PWD, but because that's the present working directory, if you move around in the filesystem, it's logical that its value would change too.
The RANDOM value, however, is in a category of its own and makes it super easy to add some pseudo-randomness to your scripts and user interaction (whether it's truly random is a far more complicated—mind-numbingly complex—issue. If you're interested, try Googling “determining the randomness of random numbers” to jump down that particular rabbit hole.
In the Bourne Again Shell (bash), RANDOM numbers are within the range of 0..MAXINT (32,767). To chop it down and make it useful, you can simply divide it by the max numeric value you seek.
In other words, if you want a random number between 1..10, for example, use the % “remainder” function with a call to expr:
$ expr $RANDOM % 10 7 $ expr $RANDOM % 10 5 $ expr $RANDOM % 10 9 $ expr $RANDOM % 10 6 $ expr $RANDOM % 10 8
Boiling this down further, how to choose between two options randomly now should be jumping out of the page at you, dear reader:
if [ "$(expr $RANDOM % 2 )" -eq "0" ] ; then
conditional expression
fi
If you wanted to be a purist, you also could write this with the $(( )) math notation, of course, as you'll see a bit later in this column.
That's enough for us to write the shell script I mentioned earlier, the one that randomly switched between two possible pages when invoked:
#!/usr/local/bin/bash url1="http://www.bing.com/" url2="http://www.google.com/" if [ "$(expr $RANDOM % 2 )" -eq "0" ] ; then echo "Location: $url1"; echo "" else echo "Location: $url2"; echo "" fi exit 0
Can you see what this example script does? If you guessed “randomly redirects you to either Google or Bing”, you're right! If not, well, what the heck? Go back and read the code again!
Now, let's say my friend said “75% of the time, I really want to take people to URL1. Can you do it, Dave?”
Here's how that might look:
if [ "$(expr $RANDOM % 100 )" -lt "75" ] ; then
(Or, even more clearly as % 4 -lt 3, for that matter.)
If you have more than two choices, you can use a case statement that makes uneven allocation a bit tricky but otherwise is straightforward:
case $(( $RANDOM % 4 )) in 0 ) echo $url1; ;; 1 ) echo $url2; ;; 2 ) echo $url3; ;; 3 ) echo $url4; ;; esac
With this in mind, we could write an n-way load-balancing script, so that when people come to the home page, they automatically would be bounced to one of the n possible servers.
The interesting step actually would be to round-robin them, based on the server load, of course, which could be done by stepping through the data using the ruptime command.
So, given the uptime output of:
$ ruptime host1 host1 16:51 up 3+53:17, 3 users, load 0.65 0.68 0.51
What we really want is to get a list of hostnames sorted by how busy those systems are, which can be generated by ruptime with the -rl flags, as shown here:
$ ruptime -r -l host1 down 16+08:34 host4 up 10+13:26, 7 users, load 0.07, 0.39, 1.04 host3 up 14+06:49, 3 users, load 0.10, 0.38, 0.49 host2 up 1+17:40, 4 users, load 0.18, 0.13, 0.09
As you can see, the first step is to screen out the hosts that aren't actually up at the present moment, then grab the first field (as it's sorted by how busy the system is at the current moment).
One approach to this could be to call ruptime every time a request comes in and just grab the first value. This can be done like so:
$ ruptime -rl | grep -v down | head -1 | cut -d\ -f1 host2
The trouble is that the systems report uptime information only approximately every minute, and calling ruptime dozens or hundreds of times per second can end up producing a problem—the least-busy system will be swamped. If you get a lot of traffic, that's not going to be a manageable solution.
Here's where we could have our friend $RANDOM step back into the picture. Instead of always simply picking the machine with the lowest load average, let's randomly choose one of the three least-busy systems. The core snippet would look like this:
getline="$(( ( $RANDOM % 3 ) + 1 ))"
targethost="$(ruptime -rl | grep -v down |
sed -n ${getline}p | cut -d\ -f1)"
With a bit more code, you could bias it so that, say, 50% of the time it would pick the least-busy system, 33% of the time it would pick the second-least-busy system, and 17% of the time it would pick the third-least-busy system. As time passed and as the load moved around, these systems would keep changing, and you'd achieve a crude but effective load-balancing system.
Knowing how easily you can select one of a number of possible paths randomly in a shell script, what else can you imagine that would be helpful or just fun?
Dave Taylor has been involved with UNIX since he first logged in to the on-line network in 1980. That means that, yes, he's coming up to the 30-year mark now. You can find him just about everywhere on-line, but start here: www.DaveTaylorOnline.com. In addition to all his other projects, Dave is now a film critic. You can read his reviews at www.DaveOnFilm.com.
Dave Taylor has been hacking shell scripts for over thirty years. Really. He's the author of the popular "Wicked Cool Shell Scripts" and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
- RSS Feeds
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- Dynamic DNS—an Object Lesson in Problem Solving
- New Products
- Validate an E-Mail Address with PHP, the Right Way
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Download the Free Red Hat White Paper "Using an Open Source Framework to Catch the Bad Guy"
- Tech Tip: Really Simple HTTP Server with Python
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




32 min 13 sec ago
3 hours 43 min ago
5 hours 59 min ago
6 hours 27 min ago
7 hours 25 min ago
8 hours 54 min ago
10 hours 3 min ago
10 hours 49 min ago
17 hours 25 min ago
23 hours 3 min ago