<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:og="http://ogp.me/ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:schema="http://schema.org/" xmlns:sioc="http://rdfs.org/sioc/ns#" xmlns:sioct="http://rdfs.org/sioc/types#" xmlns:skos="http://www.w3.org/2004/02/skos/core#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" version="2.0" xml:base="https://www.linuxjournal.com/">
  <channel>
    <title>Shell Scripting</title>
    <link>https://www.linuxjournal.com/</link>
    <description/>
    <language>en</language>
    
    <item>
  <title>How to Create a Shell Script in Linux</title>
  <link>https://www.linuxjournal.com/content/how-create-shell-script-linux</link>
  <description>  &lt;div data-history-node-id="1340840" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img loading="lazy" src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/how-to-create-a-shell-script-in-linux.jpg" width="850" height="500" alt="How to Create a Shell Script in Linux" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/suparna-ganguly" lang="" about="https://www.linuxjournal.com/users/suparna-ganguly" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Suparna Ganguly&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;Do you want to create a Shell script in your Linux system?&lt;/p&gt;

&lt;p dir="ltr"&gt;This guide will take you through how to create a shell script using multiple text editors, how to add comments, and how to use Shell variables.&lt;/p&gt;

&lt;p dir="ltr"&gt;But before heading over to creating a shell script, let’s understand what Shell scripting in Linux is.&lt;/p&gt;

&lt;h2 dir="ltr"&gt;What is Shell Scripting in Linux?&lt;/h2&gt;

&lt;p dir="ltr"&gt;So, what’s Shell scripting?&lt;/p&gt;

&lt;p dir="ltr"&gt;Shell Scripting is defined as an open-source program that’s run by Linux or Unix shell. Through shell scripting, you can write commands to be executed by the shell.&lt;/p&gt;

&lt;p dir="ltr"&gt;Lengthy and repetitive commands are usually combined into a simple command script. You can store this script and execute it whenever needed. &lt;/p&gt;

&lt;p dir="ltr"&gt;Shell scripting in Linux makes programming effortless.&lt;/p&gt;

&lt;h2 dir="ltr"&gt;Ways of Creating a Simple Shell Script in Linux&lt;/h2&gt;

&lt;p dir="ltr"&gt;Creating a simple shell script in Linux is very easy. You can do that using multiple text editors. This tutorial will show how to create a shell script with two different methods, such as 1) using the default text editor, and 2) Using the Vim text editor tool.&lt;/p&gt;

&lt;h3 dir="ltr"&gt;Method 1: Using the Default Text Editor

&lt;/h3&gt;&lt;p dir="ltr"&gt;To create a shell script using the default text editor, just follow the steps given below.&lt;/p&gt;

&lt;p dir="ltr"&gt;&lt;em&gt;Step 1: &lt;/em&gt;Create a text file having a “.sh” extension. Then type a simple script.&lt;/p&gt;

&lt;p dir="ltr"&gt;&lt;img alt="Shell Script testing.sh" class="image-max_650x650" data-entity-type="file" data-entity-uuid="insert-max_650x650-7d11ffde-c186-4c1e-9b6f-fcc9843fcd8f" height="81" src="https://www.linuxjournal.com/sites/default/files/styles/max_650x650/public/u%5Buid%5D/shell-script-testing-sh.jpg" width="650" /&gt;&lt;/p&gt;

&lt;p dir="ltr"&gt;&lt;em&gt;Step 2:&lt;/em&gt; Now don’t change the directory. And open the terminal. Using the command below, give executable access to the file created.&lt;/p&gt;

&lt;pre dir="ltr"&gt;
chmod +x testing.sh&lt;/pre&gt;

&lt;p dir="ltr"&gt;&lt;em&gt;Step 3:&lt;/em&gt; Execute the below-given script in the terminal:&lt;/p&gt;

&lt;pre dir="ltr"&gt;
./testing.sh&lt;/pre&gt;

&lt;p dir="ltr"&gt;This was a simple technique of creating a shell script in Linux using the default editor. Now, let’s look at the next method.&lt;/p&gt;

&lt;h3 dir="ltr"&gt;Method 2: Using the Vim Text Editor Tool

&lt;/h3&gt;&lt;p dir="ltr"&gt;Vim text editor tool is a tool that helps create a shell script in a Linux system. In case you don’t have it already installed, use the command to install Vim:&lt;/p&gt;

&lt;pre dir="ltr"&gt;
sudo apt install vim&lt;/pre&gt;

&lt;p dir="ltr"&gt;Now follow the steps for creating a shell script using the tool.&lt;/p&gt;

&lt;p dir="ltr"&gt;&lt;em&gt;Step 1:&lt;/em&gt; For opening the editor, simply type:&lt;/p&gt;

&lt;pre dir="ltr"&gt;
vim&lt;/pre&gt;

&lt;p dir="ltr"&gt;&lt;em&gt;Step 2:&lt;/em&gt; Once you’re in, open the terminal. Then create a bash file via:&lt;/p&gt;

&lt;pre dir="ltr"&gt;
vi testing.sh&lt;/pre&gt;

&lt;p dir="ltr"&gt;After the execution of the command, the editor will appear as below.&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/how-create-shell-script-linux" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Wed, 28 Jul 2021 16:00:00 +0000</pubDate>
    <dc:creator>Suparna Ganguly</dc:creator>
    <guid isPermaLink="false">1340840 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>How to Add a Simple Progress Bar in Shell Script</title>
  <link>https://www.linuxjournal.com/content/how-add-simple-progress-bar-shell-script</link>
  <description>  &lt;div data-history-node-id="1340809" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/nawaz-abbasi" lang="" about="https://www.linuxjournal.com/users/nawaz-abbasi" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Nawaz Abbasi&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;At times, we need to write shell scripts that are interactive and user executing them need to monitor the progress. For such requirements, we can implement a simple progress bar that gives an idea about how much task has been completed by the script or how much the script has executed.&lt;/p&gt;

&lt;p&gt;To implement it, we only need to use the “echo” command with the following options and a backslash-escaped character.&lt;/p&gt;

&lt;pre&gt;
-n : do not append a newline
-e : enable interpretation of backslash escapes
\r : carriage return (go back to the beginning of the line without printing a newline)
&lt;/pre&gt;

&lt;p&gt;For the sake of understanding, we will use “sleep 2” command to represent an ongoing task or a step in our shell script. In a real scenario, this could be anything like downloading files, creating backup, validating user input, etc. Also, to give an example we are assuming only four steps in our script below which is why we are using 20,40,60,80 (%) as progress indicator. This can be adjusted as per the number of steps in a script. For instance, a script with three steps can be represented by 33,66,99 (%) or a script with ten steps can be represented by 10-90 (%) as progress indicator.&lt;/p&gt;

&lt;p&gt;The implementation looks like the following:&lt;/p&gt;

&lt;pre&gt;
echo -ne '&gt;&gt;&gt;                       [20%]\r'
# some task
sleep 2
echo -ne '&gt;&gt;&gt;&gt;&gt;&gt;&gt;                   [40%]\r'
# some task
sleep 2
echo -ne '&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;            [60%]\r'
# some task
sleep 2
echo -ne '&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;   [80%]\r'
# some task
sleep 2
echo -ne '&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;[100%]\r'
echo -ne '\n'
&lt;/pre&gt;

&lt;p&gt;In effect, every time the “echo” command executes, it replaces the output of the previous “echo” command in the terminal thus representing a simple progress bar. The last “echo” command simply enters a newline (\n) in the terminal to resume the prompt for the user.&lt;/p&gt;

&lt;p&gt;The execution looks like the following:&lt;/p&gt;

&lt;p&gt;&lt;img alt="simple progress bar shell execution" class="image-max_1300x1300" data-entity-type="file" data-entity-uuid="insert-max_1300x1300-34f6f846-ebd9-4111-b403-8212b62d5da7" height="535" src="https://www.linuxjournal.com/sites/default/files/styles/max_1300x1300/public/u%5Buid%5D/simple-progress-bar-shell.png" width="583" /&gt;&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/how-add-simple-progress-bar-shell-script" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Mon, 26 Oct 2020 18:40:25 +0000</pubDate>
    <dc:creator>Nawaz Abbasi</dc:creator>
    <guid isPermaLink="false">1340809 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Quick Tutorial on How to Use Shell Scripting in Linux: Coin Toss App</title>
  <link>https://www.linuxjournal.com/content/quick-tutorial-how-use-shell-scripting-linux</link>
  <description>  &lt;div data-history-node-id="1340801" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/nawaz-abbasi" lang="" about="https://www.linuxjournal.com/users/nawaz-abbasi" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Nawaz Abbasi&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;Simply put, a Shell Script is a program that is run by a UNIX/Linux shell. It is a file that contains a series of commands which are executed sequentially as if they were entered on the command line interface (CLI) or terminal.&lt;/p&gt;

&lt;p&gt;In this quick tutorial on Shell Scripting, we will write a simple program to &lt;strong&gt;toss a coin&lt;/strong&gt;. Basically, the output of our program should be either HEADS or TAILS (of course, randomly).&lt;/p&gt;

&lt;p&gt;To start with, the first line of a shell script should indicate which interpreter/shell is to be used to execute the script. In this tutorial we will be using &lt;code&gt;/bin/bash&lt;/code&gt; and it will be denoted as &lt;code&gt;#!/bin/bash&lt;/code&gt; which is called a &lt;em&gt;shebang!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, we will be using an internal Bash function - a shell variable named RANDOM. It returns a random (actually, pseudorandom) integer in the range &lt;code&gt;0-32767&lt;/code&gt;. We will use this variable to get 2 random values – either 0 (for HEADS) or 1 (for TAILS). This will be done via a simple arithmetic operation in shell using % (Modulus operator, returns remainder), &lt;code&gt;$((RANDOM%2))&lt;/code&gt; and this will be stored in a result variable. So, the second line of our program becomes &lt;code&gt;Result=$((RANDOM%2))&lt;/code&gt; – Note that there should be no space around = (assignment operator) while assigning value to a variable in shell scripts.&lt;/p&gt;

&lt;p&gt;At last, we just need to print HEADS if we got 0 or TAILS if we got 1, in the &lt;code&gt;Result&lt;/code&gt; variable. Perhaps you guessed it by now, we will use if conditional statements for this. Within the conditions, we will compare the value of &lt;code&gt;Result&lt;/code&gt; variable with 0 and 1; and print HEADS or TAILS accordingly. For this, the operator for integer comparison &lt;code&gt;-eq&lt;/code&gt; (is equal to) is used to check if the value of two operands are equal or not.&lt;/p&gt;

&lt;p&gt;Ergo, our shell script looks like the following:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;#!/bin/bash
Result=$((RANDOM%2))
if [[ ${Result} -eq 0 ]]; then
    echo HEADS
elif [[ ${Result} -eq 1 ]]; then
    echo TAILS
fi&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Let’s say we name the script &lt;em&gt;cointoss.sh&lt;/em&gt; – Note that .sh is only to make it identifiable for user(s) that the file/script is a shell script. And, Linux is an Extensionless system.&lt;/p&gt;

&lt;p&gt;Finally, to run the script we need to make it executable and that can be done by using the &lt;code&gt;chmod&lt;/code&gt; command – &lt;code&gt;chmod +x cointoss.sh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Few script executions:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;$ ./cointoss.sh

TAILS

$ ./cointoss.sh

HEADS

$ ./cointoss.sh

HEADS

$ ./cointoss.sh

TAILS&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;To wrap up, in this quick tutorial about writing shell scripts, we learned about &lt;em&gt;shebang, RANDOM&lt;/em&gt;, variable assignment, an arithmetic operation using Modulus operator &lt;code&gt;%&lt;/code&gt;, if conditional statements, integer comparison operator &lt;code&gt;-eq&lt;/code&gt; and executing a shell script.&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/quick-tutorial-how-use-shell-scripting-linux" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Mon, 12 Oct 2020 19:08:19 +0000</pubDate>
    <dc:creator>Nawaz Abbasi</dc:creator>
    <guid isPermaLink="false">1340801 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Bash Shell Games: Let's Play Go Fish!</title>
  <link>https://www.linuxjournal.com/content/bash-shell-games-lets-play-go-fish</link>
  <description>  &lt;div data-history-node-id="1340682" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;How to begin developing a computer version of the popular card game.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
Between the previous 163 columns I've written here in &lt;em&gt;Linux Journal&lt;/em&gt; and the dozens
of games I programmed and explored during the creation of my &lt;em&gt;Wicked Cool
Shell Scripts&lt;/em&gt; book, I've written a lot of Bash shell games. The challenge is to
find one that's simple enough where a shell script will work, but isn't so
simple that it ends up being only a half-dozen lines.
&lt;/p&gt;

&lt;p&gt;
Magic 8-Ball is a perfect example. It turns out that the entire "predict the future" gizmo
was really just a 20-sided die floating in dark purple fluid. So an array of 20 possible
values and a random number selector and boom—you've got a magic 8-ball script:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
#!/bin/sh

# magic 8 ball. Yup. Pick a random number, output message

# messages harvested from the Wikipedia entry

answers=("It is certain." "It is decidedly so."
  "Without a doubt." "Yes - definitely."
  "You may rely on it." "As I see it, yes." "Most likely."
  "Outlook good." "Yes." "Signs point to yes."
  "Reply hazy, try again." "Ask again later."
  "Better not tell you now." "Cannot predict now."
  "Concentrate and ask again." "Don't count on it."
  "My reply is no." "My sources say no."
  "Outlook not so good." "Very doubtful.")

echo "Oh! Magic 8 Ball, Please Tell Me True..." ; echo ""
/bin/echo -n "What is your question? "
read question

answer=$(( $RANDOM % 20 ))

echo ""
echo "I have looked into the future and I say: "
echo "     ${answers[$answer]}" ; echo ""

exit 0
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Let's do a quick run to see if I'm the most popular &lt;em&gt;LJ&lt;/em&gt; writer:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
$ sh magic8.sh
Oh! Magic 8 Ball, Please Tell Me True...

What is your question? Am I the most popular LJ writer?

I have looked into the future and I say:
     My reply is no.
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Ouch, that's harsh. I write the darn divination program, and it just drops a brick on my foot.
Yeesh.
&lt;/p&gt;

&lt;p&gt;
More seriously, Magic 8 Ball is too simple to make an interesting shell script. By
contrast, &lt;em&gt;Call of Duty&lt;/em&gt; is way too complex, even if I did a version with text output
instead of gorgeously rendered 3D graphics.
&lt;/p&gt;

&lt;span class="h3-replacement"&gt;
Card Game Function Library&lt;/span&gt;

&lt;p&gt;
That's why card games prove to be good as programming challenges or exercises: the
core mechanism of a 52-card random deck is pretty straightforward, so it's all
about the actual cardplay.
&lt;/p&gt;

&lt;p&gt;
Not only that, but as I've written before about card games as shell scripts, I
already have a handy set of functions to create, shuffle and display cards out of a
deck. If you want to rummage in the archives, I've tackled &lt;em&gt;Acey-Deucey&lt;/em&gt;,
&lt;em&gt;Baccarat&lt;/em&gt;
and some bits and pieces of &lt;em&gt;Cribbage&lt;/em&gt;.
&lt;/p&gt;

&lt;p&gt;
In order to jump right into the new game that I'm going to describe how to build, &lt;em&gt;Go Fish!&lt;/em&gt;,
let's steal the following functions from my earlier scripts:
&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/bash-shell-games-lets-play-go-fish" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Tue, 30 Jul 2019 12:00:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340682 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Finishing Up the Bash Mail Merge Script</title>
  <link>https://www.linuxjournal.com/content/finishing-bash-mail-merge-script</link>
  <description>  &lt;div data-history-node-id="1340605" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;Finally, I'm going to finish the mail merge script, just in time for
Replicant Day.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
Remember the &lt;a href="https://www.linuxjournal.com/content/fun-mail-merge-and-cool-bash-arrays"&gt;mail
merge script&lt;/a&gt; I started writing a while back? Yeah,
that was quite some
time ago. I got sidetracked with the &lt;em&gt;Linux Journal&lt;/em&gt; Anniversary special
issue (see my article &lt;a href="https://www.linuxjournal.com/content/back-day-unix-minix-and-linux"&gt;"Back
in the Day: UNIX, Minix and Linux"&lt;/a&gt;), and then I spun off on a
completely different tangent for my last article (&lt;a href="https://www.linuxjournal.com/content/breaking-apache-log-files-analysis"&gt;"Breaking
Up Apache Log Files for Analysis"&lt;/a&gt;). I blame it on...
&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;SQUIRREL!&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
Oh, sorry, back to topic here. I was developing a shell
script that would let you specify a text document with
embedded field names that could be substituted iteratively
across a file containing lots of field values.
&lt;/p&gt;

&lt;p&gt;
Each field was denoted by &lt;code&gt;#fieldname#&lt;/code&gt;, and I identified two
categories of fieldnames: fixed and dynamic. A fixed value
might be &lt;code&gt;#name#&lt;/code&gt;, which would come directly out of the data
file, while a dynamic value could be &lt;code&gt;#date#&lt;/code&gt;, which would be
the current date.
&lt;/p&gt;
&lt;p&gt;
More interesting, I also proposed calculated values,
specifically &lt;code&gt;#suggested#&lt;/code&gt;, which would be a value calculated
based on &lt;code&gt;#donation#&lt;/code&gt;, and &lt;code&gt;#date#&lt;/code&gt;, which would be replaced by
the current date. The super-fancy version would have a
simple language where you could define the relationship between
variables, but let's get real. Mail merge. It's just mail
merge.
&lt;/p&gt;

&lt;span class="h3-replacement"&gt;
Reading and Assigning Values&lt;/span&gt;

&lt;p&gt;
It turns out that the additions needed for this script aren't
too difficult. The basic data file has comma-separated
field names, then subsequent lines have the values
associated with those fields.
&lt;/p&gt;

&lt;p&gt;
Here's that core code:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
if [ $lines -eq 1 ] ; then # field names
# grab variable names
declare -a varname=($f1 $f2 $f3 $f4 $f5 $f6 $f7)
else # process fields

# grab values for this line (can contain spaces)
declare -a value=("$f1" "$f2" "$f3" "$f4" "$f5" "$f6" "$f7")
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
The &lt;code&gt;declare&lt;/code&gt; function turns out to be ideal for this,
allowing you to create an array &lt;code&gt;varname&lt;/code&gt; based on the
contents of the first line, then keep replacing the values
of the array &lt;code&gt;value&lt;/code&gt;, so that &lt;code&gt;varname[1] =
value[1]&lt;/code&gt;, and so
on.
&lt;/p&gt;

&lt;p&gt;
To add the additional variables &lt;code&gt;#date#&lt;/code&gt; and
&lt;code&gt;#suggested#&lt;/code&gt;, you
simply can append them to the &lt;code&gt;varname&lt;/code&gt; and
&lt;code&gt;value&lt;/code&gt; arrays. The
first one is easy, but it did highlight a weakness in the
original code that I had to fix by adding quotes as shown:

&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/finishing-bash-mail-merge-script" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Thu, 04 Jul 2019 12:00:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340605 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Breaking Up Apache Log Files for Analysis</title>
  <link>https://www.linuxjournal.com/content/breaking-apache-log-files-analysis</link>
  <description>  &lt;div data-history-node-id="1340584" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;Dave tackles analysis of the ugly Apache web server log.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
I know, in my last article I promised I'd jump back into the &lt;a href="https://www.linuxjournal.com/content/fun-mail-merge-and-cool-bash-arrays"&gt;mail merge
program&lt;/a&gt; I started building a while back. Since I'm having some hiccups
with my AskDaveTaylor.com web server, however, I'm going to claim
editorial privilege and bump that yet again.
&lt;/p&gt;

&lt;p&gt;
What I need to do is be able to process Apache log files and isolate
specific problems and glitches that are being encountered—a perfect use
for a shell script. In fact, I have a script of this nature that offers
basic analytics in my book &lt;em&gt;Wicked Cool Shell Scripts&lt;/em&gt; from
O'Reilly, but this is a bit more specific.
&lt;/p&gt;

&lt;span class="h3-replacement"&gt;
Oh Those Ugly Log Files&lt;/span&gt;

&lt;p&gt;
To start, let's take a glance at a few lines out of the latest
log file for the site:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
$ head sslaccesslog_askdavetaylor.com_3_8_2019
18.144.59.52 - - [08/Mar/2019:06:10:09 -0600] "GET /wp-content/
↪themes/jumpstart/framework/assets/js/nivo.min.js?ver=3.2
 ↪HTTP/1.1" 200 3074
"https://www.askdavetaylor.com/how-to-play-dvd-free-windows-
↪10-win10/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
 ↪AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
 ↪64.0.3282.140 Safari/537.36 Edge/18.17763 X-Middleton/1"
 ↪52.53.151.37 - - [08/Mar/2019:06:10:09 -0600] "GET
 ↪/wp-includes/js/jquery/jquery.js?ver=1.12.4 HTTP/1.1"
 ↪200 33766 "https://www.askdavetaylor.com/how-to-play
↪-dvd-free-windows-10-win10/" "Mozilla/5.0 (Windows NT
 ↪10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
 ↪Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763
 ↪X-Middleton/1" 18.144.59.52 - - [08/Mar/2019:06:10:09
 ↪-0600] "GET /wp-content/plugins/google-analytics-for-
↪wordpress/assets/js/frontend.min.js?ver=7.4.2 HTTP/1.1"
 ↪200 2544 "https://www.askdavetaylor.com/how-to-play
↪-dvd-free-windows-10-win10/"
 ↪"Mozilla/5.0 (Windows NT 10.0; Win64; x64)
 ↪AppleWebKit/537.36 (KHTML, like Gecko)
 ↪Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763
 ↪X-Middleton/1"
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
It's big and ugly, right? Okay, then let's just isolate a single entry to
see how it's structured:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
18.144.59.52 - - [08/Mar/2019:06:10:09 -0600] "GET
 ↪/wp-content/themes/jumpstart/framework/assets/js/
↪nivo.min.js?ver=3.2 HTTP/1.1" 200 3074
"https://www.askdavetaylor.com/how-to-play-dvd-free-windows-
↪10-win10/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140
 ↪Safari/537.36 Edge/18.17763 X-Middleton/1"
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
That's still obfuscated enough to kick off a migraine!
&lt;/p&gt;

&lt;p&gt;
Fortunately, the &lt;a href="http://www.apache.org"&gt;Apache website&lt;/a&gt;
has a somewhat clearer
explanation of what's known as the custom log file format that's in
use on my server. Of course, it's described in a way that only a
programmer could love:

&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/breaking-apache-log-files-analysis" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Mon, 27 May 2019 11:00:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340584 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>What The @#$%&amp;! (Heck) is this #! (Hash-Bang) Thingy In My Bash Script</title>
  <link>https://www.linuxjournal.com/content/what-heck-hash-bang-thingy-my-bash-script</link>
  <description>  &lt;div data-history-node-id="1340624" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/mitch-frazier" lang="" about="https://www.linuxjournal.com/users/mitch-frazier" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Mitch Frazier&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;You've seen it a million times—the hash-bang (#!) line at the top of a script—whether it be Bash, Python, Perl or some other scripting language. And, I'm sure you know what its purpose is: it specifies the script interpreter that's used to execute the script. But, do you know how it actually works? Your initial thought might be that your shell (bash) reads that line and then executes the specified interpreter, but that's not at all how it works. How it actually works is the main focus of this post, but I also want to introduce how you can create your own version of "hash-bang" if you're so inclined.&lt;/p&gt;
&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/what-heck-hash-bang-thingy-my-bash-script" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Fri, 10 May 2019 11:30:00 +0000</pubDate>
    <dc:creator>Mitch Frazier</dc:creator>
    <guid isPermaLink="false">1340624 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Fun with Mail Merge and Cool Bash Arrays</title>
  <link>https://www.linuxjournal.com/content/fun-mail-merge-and-cool-bash-arrays</link>
  <description>  &lt;div data-history-node-id="1340460" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;Creating a sed-based file substitution tool.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
A few weeks ago, I was digging through my spam folder and found an email message
that started out like this:
&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
Dear #name#
Congratulations on winning the $15.7 million lottery payout!
To learn how to claim your winnings, please...
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Obviously, it was a scam (does anyone actually fall for these?), but what captured my
attention was the &lt;code&gt;#name#&lt;/code&gt; sequence. Clearly that was a fail on the part of the sender who
presumably didn't know how to use AnnoyingSpamTool 1.3 or whatever the heck
he or she was using.
&lt;/p&gt;

&lt;p&gt;
The more general notation for bulk email and file transformations is pretty
interesting, however. There are plenty of legitimate reasons to use this sort
of substitution, ranging from email newsletters (like the one I send every week
from &lt;a href="https://www.askdavetaylor.com"&gt;AskDaveTaylor.com&lt;/a&gt;—check it out!) to stockholder announcements and much
more.
&lt;/p&gt;

&lt;p&gt;
With that as the inspiration, let's build a tool that offers just this
capability.
&lt;/p&gt;

&lt;p&gt;
The simple version will be a 1:1 substitution, so &lt;code&gt;#name#&lt;/code&gt; becomes, say,
"Rick Deckard", while &lt;code&gt;#first#&lt;/code&gt; might be "Rick" and
&lt;code&gt;#last#&lt;/code&gt; might
be "Deckard". Let's build on that, but let's start
small.
&lt;/p&gt;

&lt;span class="h3-replacement"&gt;
Simple Word Substitution in Linux&lt;/span&gt;

&lt;p&gt;
There are plenty of ways to tackle the word substitution from the command line,
ranging from Perl to awk, but here I'm using the original UNIX command
&lt;code&gt;sed&lt;/code&gt; (stream editor) designed for exactly this purpose. General notation for a
substitution is s/old/new/, and if you tack on a &lt;code&gt;g&lt;/code&gt; at the end, it
matches every occurrence on a line, not only the first, so the full command
is s/old/new/g.
&lt;/p&gt;

&lt;p&gt;
Before going further, here's a simple document that has necessary
substitutions embedded:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
$ cat convertme.txt
#date#

Dear #name#, I wanted to start by again thanking you for your
generous donation of #amount# in #month#. We couldn't do our
work without support from humans like you, #first#.

This year we're looking at some unexpected expenses,
particularly in Sector 5, which encompasses #state#, as you
know. I'm hoping you can start the year with an additional
contribution? Even #suggested# would be tremendously helpful.

Thanks for your ongoing support. With regards,

Rick Deckard
Society for the Prevention of Cruelty to Replicants
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Scan through it, and you'll see there's a lot of substitutions to do:
&lt;code&gt;#date#&lt;/code&gt;, &lt;code&gt;#name#&lt;/code&gt;,
&lt;code&gt;#amount#&lt;/code&gt;, &lt;code&gt;#month#&lt;/code&gt;, &lt;code&gt;#first#&lt;/code&gt;,
&lt;code&gt;#state#&lt;/code&gt; and &lt;code&gt;#suggested#&lt;/code&gt;. It turns out that
&lt;code&gt;#date#&lt;/code&gt; will
be replaced with the current date, and &lt;code&gt;#suggested#&lt;/code&gt; is one that'll be
calculated as the letter is processed, but that's for a bit later, so
stay tuned for that.
&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/fun-mail-merge-and-cool-bash-arrays" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Mon, 25 Mar 2019 11:30:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340460 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Converting Decimals to Roman Numerals with Bash</title>
  <link>https://www.linuxjournal.com/content/converting-decimals-roman-numerals-bash</link>
  <description>  &lt;div data-history-node-id="1340357" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;Decimals to Roman numerals—here we hit all the limitations of Bash
shell scripting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
My last few articles have given me a chance to relive my undergraduate
computer science degree and code a Roman numeral to decimal converter.
It's quite handy when you're watching old movies (when was MCMLVII
anyway?), and
the basic coding algorithm was reasonably straightforward. (See Dave's &lt;a href="https://www.linuxjournal.com/content/roman-numerals-and-bash"&gt;"Roman
Numerals and Bash"&lt;/a&gt; and &lt;a href="https://www.linuxjournal.com/content/more-roman-numerals-and-bash"&gt;"More
Roman Numerals and Bash"&lt;/a&gt;.)
&lt;/p&gt;

&lt;p&gt;
The trick with Roman numerals, however, is that it's what's known
as a &lt;em&gt;subtractive notation&lt;/em&gt;. In other words, it's not a position → value
or even symbol → value notation, but a sort of hybrid. MM = 2000, and C =
100, but MMC and MCM are quite different: the former is 2100, and the
latter is 1000 + (–100 + 1000) = 1900.
&lt;/p&gt;

&lt;p&gt;
This means that the conversion isn't quite as simple as a mapping
table, which makes it a good homework assignment for young comp-sci
students!
&lt;/p&gt;

&lt;span class="h3-replacement"&gt;
Let's Write Some Code&lt;/span&gt;

&lt;p&gt;
In the Roman numeral to decimal conversion, a lot of the key work was done
by this simple function:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
mapit() {
   case $1 in
     I|i) value=1 ;;
     V|v) value=5 ;;
     X|x) value=10 ;;
     L|l) value=50 ;;
     C|c) value=100 ;;
     D|d) value=500 ;;
     M|m) value=1000 ;;
      * ) echo "Error: Value $1 unknown" &gt;&amp;2 ; exit 2 ;;
   esac
}
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
You'll need this function to proceed, but as a cascading set of
conditional statements. Indeed, in its simple form, you could code a decimal to Roman
numeral converter like this:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
while [ $decvalue -gt 0 ] ; do

  if [ $decvalue -gt 1000 ] ; then
    romanvalue="$romanvalue M"
    decvalue=$(( $decvalue - 1000 ))
  elif [ $decvalue -gt 500 ] ; then
    romanvalue="$romanvalue D"
    decvalue=$(( $decvalue - 500 ))
  elif [ $decvalue -gt 100 ] ; then
    romanvalue="$romanvalue C"
    decvalue=$(( $decvalue - 100 ))
  elif [ $decvalue -gt 50 ] ; then
    romanvalue="$romanvalue L"
    decvalue=$(( $decvalue - 50 ))
  elif [ $decvalue -gt 10 ] ; then
    romanvalue="$romanvalue X"
    decvalue=$(( $decvalue - 10 ))
  elif [ $decvalue -gt 5 ] ; then
    romanvalue="$romanvalue V"
    decvalue=$(( $decvalue - 5 ))
  elif [ $decvalue -ge 1 ] ; then
    romanvalue="$romanvalue I"
    decvalue=$(( $decvalue - 1 ))
  fi

done
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
This actually works, though the results are, um, a bit clunky:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
$ sh 2roman.sh 25
converts to roman numeral  X X I I I I I
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Or, more overwhelming:

&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/converting-decimals-roman-numerals-bash" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Mon, 18 Feb 2019 12:30:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340357 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Writing Secure Shell Scripts</title>
  <link>https://www.linuxjournal.com/content/writing-secure-shell-scripts</link>
  <description>  &lt;div data-history-node-id="1340410" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;Don't expose your system with sloppy scripts!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
Although a Linux desktop or server is less susceptible to viruses and malware
than a typical Windows device, there isn't a device on the internet that
isn't eventually attacked. The culprit might be the stereotypical nerd in
a bedroom testing his or her hacker chops (think Matthew Broderick in &lt;em&gt;War
Games&lt;/em&gt; or Angelina Jolie in &lt;em&gt;Hackers&lt;/em&gt;). Then again, it might be an
organized military, criminal, terrorist or other funded entity creating
massive botnets or stealing millions of credit cards via a dozen redirected
attack vectors.
&lt;/p&gt;

&lt;p&gt;
In any case, modern systems face threats that were unimaginable in the early
days of UNIX development and even in the first few years of Linux as a hobbyist
reimplementation of UNIX. Ah, back in the day, the great worry was about
copyrighted code, and so useful tools constantly were being re-implemented from
scratch to get away from the AT&amp;T Bell Labs licenses and so forth.
&lt;/p&gt;

&lt;p&gt;
I have personal experience with this too. I rewrote the &lt;em&gt;Hunt the
Wumpus&lt;/em&gt; game
&lt;code&gt;wumpus&lt;/code&gt; from scratch for BSD 4.2 when the Berkeley crowd was trying to get
away from AT&amp;T UNIX legal hassles. I know, that's not the greatest claim to fame,
but I also managed to cobble together a few other utilities in my time too.
&lt;/p&gt;

&lt;p&gt;
Evolution worked backward with the internet, however. In real life, the
lawless Wild West was gradually tamed, and law-abiding citizens replaced the
outlaws and thugs of the 1850s and the Gold Rush. Online, it seems that there
are more, smarter and better organized digital outlaws than ever.
&lt;/p&gt;

&lt;p&gt;
Which is why one of the most important steps in learning how to write shell
scripts is to learn how to ensure that your scripts are secure—even if
it's just your own home computer and an old PC you've converted into
a Linux-based media server with Plex or similar.
&lt;/p&gt;

&lt;p&gt;
Let's have a look at some of the basics.
&lt;/p&gt;

&lt;span class="h3-replacement"&gt;
Know the Utilities You Invoke&lt;/span&gt;

&lt;p&gt;
Here's a classic trojan horse attack: an attacker drops a script called
&lt;code&gt;ls&lt;/code&gt;
into /tmp, and it simply checks to see the userid that invoked it, then hands
off its entire argument sequence to the real /bin/ls. If it recognizes userid
= root, it makes a copy of /bin/sh into /tmp with an innocuous name, then
changes its permission to setuid root.
&lt;/p&gt;

&lt;p&gt;
This is super easy to write. Here's a version off the top of my head:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
#!/bin/sh

if [ "$USER" = "root" ] ; then
  /bin/cp /bin/sh /tmp/.secretshell
  /bin/chown root /tmp/.secretshell
  /bin/chmod 4666 root /tmp/.secretshell
fi

exec /bin/ls $*
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
I hope you understand what just happened. This simple little script has
created a shell that always grants its user root access to the Linux system.
Yikes. Fancier versions would remove themselves once the root shell has been
created, leaving no trace of how this transpired.
&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/writing-secure-shell-scripts" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Tue, 05 Feb 2019 12:30:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340410 at https://www.linuxjournal.com</guid>
    </item>

  </channel>
</rss>
