for loops in bash

I don’t do much shell scripting, but every once in a while I use it to automate things. I was playing around with bash today and thought this might interest others.

Define an array variable
$ servers=(server purple yellow dan);
$ echo $servers
server

Redefine it.
$ servers=(firstserver server purple yellow dan);
$ echo $servers
firstserver

That’s not what I want. So how do we access the values? Let’s try a for loop.
$ for name in $servers; do echo $name; done;
$ echo $servers
firstserver

Well that didn’t do it. Let’s try to access the second value with array notation.
$ for name in $servers; do echo $servers[1]; done;
firstserver[1]

If you look carefully at this you’ll notice that what is happening is that you are concatenating the return value from $server with [1]. Try it again with this line.

$ for name in $servers; do echo $servers[a]; done;
firstserver[a]

And again.
$ for name in $servers; do echo $servers.a; done;
firstserver.a

As long as you use a character that is not a valid part of a variable name, you get concatenation.
e.g. don’t use an alphanumeric.
$ for name in $servers; do echo $serversabc; done;

There is no variable called serverabc, so you get a blank line.

It turns out that bash has weird syntax for working with variables.
$ echo ${servers[2]}
purple

Add another value.
$ servers[5]=finalvalue
$ echo ${servers[5]}
finalvalue

So how about we separate out the loop variable like this?
$ for name in $servers; do echo $servers${name}; done;
firstserverfirstserver

Well, we’re getting warmer.
$ for name in $servers; do echo $name; done;
firstserver

This is getting frustrating. Let’s back up and try just listing a bunch of stuff in a list.
$ for name in firstserver server purple yellow dan finalvalue; do echo $name; done;
firstserver
server
purple
yellow
dan
finalvalue

So we can make a for loop iterate through items, but the normal way of accessing elements of an array doesn’t work in bash. It turns out that you need special syntax.

$ echo ${servers[@]}
firstserver server purple yellow finalvalue finalvalue

And to loop through everything like we wanted to do at the start.
$ for name in ${servers[@]}; do echo $name; done;
firstserver
server
purple
yellow
dan
final value

That wasn’t so hard was it?

Put footer at the bottom of the page

This only works if the page content is not bigger than the window.
Try it yourself or check it out at FixedFooter.


<!DOCTYPE html>
<html lang="en">

<head>
  <title>Fixed Footer Example</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

  <style type="text/css">
  html, body, #container {
      height: 100%;
      margin: auto;
      text-align: center;
  }

  #footer {
        position:absolute;
        bottom:0;
        width:100%;
        margin: auto;
        height:60px;
        text-align: center;
    }

  </style>
</head>
<body>

<div id="container">
    <h1>This is the main content</h1>
    <p>If it is bigger than the window, then the footer will play over it.</p>
    <p>The footer can be inside or outside of the container.</p>
</div>

<div id="footer">
    <p>This is the footer content.</p>
</div>

</body>
</html>

Rollover Text on Images

Here are two ways to do image rollovers. One is pure CSS and the other uses javascript. You can view them here.

The CSS version uses a background image and the hover is a transparent png with just the text in it.

The javascript version swaps out images on rollover and click.


<style type="text/css">

.image {
    height:300px;
    width:500px;
    display: block;
    float:left;
    clear: left;
    margin-top:20px;
}

.rollover img {
    opacity: 0;
}

.rollover img:hover {
    opacity: 1.0;
}

</style>

<div class="image" style="background:url(Roscher_Photo_1.jpg);">
    <a class="rollover" href=""><img src="Roscher_Photo_1_Text.png" alt="Rollover text" /></a>
</div>

<div class="image">
    <a href="Roscher_Photo_1.jpg"
    onmouseover="if (document.images) document.imagename1.src='Roscher_Photo_1_Annotated.jpg';"
    onmouseout="if (document.images)  document.imagename1.src='Roscher_Photo_1.jpg';">

        <img src="Roscher_Photo_1.jpg" name="imagename1"
        alt="Moving the cursor over the image will bring up an annotated version.
        Clicking on the image will bring up the highest resolution version available.">
    </a>
</div>

MySQL won’t reboot

After the 100% full hard disk problem I couldn’t get MySQL to restart. I looked at the error logs and found these lines.


151010 16:51:18 [ERROR] /usr/sbin/mysqld: Table './SS_connellsville/alerts' is marked as crashed and should be repaired
151010 16:51:18 [Warning] Checking table:   './SS_connellsville/alerts'
151010 16:51:56 [ERROR] /usr/sbin/mysqld: Table './SS_greensburg/values_RSSI_3' is marked as crashed and should be repaired
151010 16:51:56 [Warning] Checking table:   './SS_greensburg/values_RSSI_3'
151010 16:51:58 [ERROR] /usr/sbin/mysqld: Table './master/node_groups' is marked as crashed and should be repaired
151010 16:51:58 [Warning] Checking table:   './master/node_groups'

A stackoverflow post recommended using mysqlcheck. It must be used when the mysqld server is running. I couldn’t see how to set it to just repair the databases that were causing problems, but I figured that it wouldn’t hurt to run it on all of them. I was a bit concerned that it would run into problems when the cron jobs ran, but I set it running anyway. It changed the record count on all of the databases and ran for many hours. At least six, but I stopped monitoring and let it run overnight. I stopped MySQL and did a restart and it started without errors.


mysqlcheck --repair --use-frm --all-databases