    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Stufftar</title>
        <link>https://members.accu.org/index.php/journals/2226</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">Overload Journal #132 - April 2016 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c360/">o132</a>
                    (10)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c360-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c360+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Stufftar</h1>
<p><strong>Author:</strong>&nbsp;Martin Moene</p>
<p>
<strong>Date:</strong> 04 April 2016 21:36:05 +01:00 or Mon, 04 April 2016 21:36:05 +01:00</p>
<p><strong>Summary:</strong>&nbsp;How do you quickly transfer data from one machine to another? Ian Bruntlett shows us the bash script he uses.</p>
<p><strong>Body:</strong>&nbsp;<p class="quote">A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over, beginning with a working simple system.<br />~ John Gall</p>

<p>Some time ago Frances Buontempo was looking for articles for <em>Overload</em>. I mentioned in an e-mail that I had a backup script called stufftar that I could write about. Frances kindly provided the questions that this article was built on.</p>

<h2>What inspired it? Were you trying to solve a specific problem?</h2>

<p>I use both Ubuntu and Lubuntu Linux. I am a volunteer tester of both. For personal use, I use Ubuntu and LUbuntu and I want to keep up to date so I needed some method to create backups and transport of key files and folders as flexibly as possible.</p>

<p>Initially I was backing up key files (all of <span class="filename">~/stuff</span>) to a .tar.gz file. Then I decided I wanted to automate it a bit so I worked out how to automatically create its destination filename:</p>

<pre class="programlisting">
  DESTINATION_FILENAME=$1`date &quot;+_%d_%B_%Y.tar.gz&quot;`</pre>
  
<p>Then I added commands to display the time taken to do the backups using the line:</p>

<pre class="programlisting">
/usr/bin/time -f &quot;%E mins:secs &quot; tar -czf $DESTINATION_FILENAME $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15} ${16} ${17} ${18} ${19} ${20}</pre>

<p>I had to call time from <span class="filename">/usr/bin</span> because bash was â€˜hidingâ€™ it with its own, less flexible, <code>time</code> implementation, which doesnâ€™t support the options I wanted.</p>

<p>Because of my inexperience with bash, testing was very important to me. As new features were developed, I would put a â€˜testâ€™ framework in place, thoroughly test each new feature and then remove the â€˜testâ€™ framework. Having functions ensure they had been given sufficient parameters was particularly important.</p>

<p>As time went by, I added more options. In particular I wanted to backup individual folders leading to the options (<code>desktop</code>, <code>extra</code>, <code>rpg</code>, <code>home</code> and <code>localhost</code>) being implemented. For convenience I wanted to be able to specify â€˜backup everythingâ€™ so I implemented the <code>all</code> option. To keep things transparent, I implemented the <code>verbose</code> option for stufftar to output more information about what it is currently doing. I typically have a refurbished Lenovo ThinkPad T420 (from www.tier1online.com) as my main computer (hostname newton) running Ubuntu Linux. I have an old 32 bit Samsung NC10 that I take with me when visiting family (running lubuntu Linux). I back up my .tar.gz files to USB flash drive. I also back them up to external hard drives. Iâ€™ve got three external 500GB hard drives and, once a month, I copy that monthâ€™s latest .tar.gz files to one of them. I rotate my use of external hard drive so that Iâ€™m backing up to the one containing the oldest backup of the set. About once a year I archive everything to dual-layer DVD-R â€“ mainly as individual folders but I put the â€˜homeâ€™ and â€˜localhostâ€™ .tar.gz files as is onto the DVD-R.</p>

<h2>What does it do?</h2>

<p>Iâ€™ve got a bunch of important digital files I carry around and backup to USB flash drives and hard drives. My <span class="filename">~/Desktop</span> files are my key files for general use. Other folders are <span class="filename">~/stuff</span> (the original folder I put my â€˜stuffâ€™ in), <span class="filename">~/extra</span> (the folder I moved from <span class="filename">~/stuff</span> when it became too large), <span class="filename">~/RPG</span> (the folder I use to keep RPG PDFs etc in). The <code>home</code> option backs up key shell scripts. The <code>localhost</code> option backs up key files (<span class="filename">/var/www/</span>) from LAMP studies.</p>

<h2>How do you use it?</h2>

<p>For help type in ./stufftar and it gives you a list of command line options (see Figure 1).</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
ian@newton:~$ ./stufftar
./stufftar Usage : stufftar followed by one or more commands: desktop, 
extra, rpg, localhost, stuff, home and all
All data files are:-
1. Named after the relevant command name, followed by day number, month, year.
   For example: Desktop_01_March_2014.tar.gz
2. Are created using the tar command with file compression switched on.

Explanation of stufftar commands:-
desktop   - copy desktop files to a desktop tar file
extra     - copy extra to a tar file â€“  Linux Voice, Overload, QL Today
stuff     - copy stuff â€“ anything I want to keep (main files are here)
rpg       - copy ~/RPG to a tar file
home      - copy refurb, stufftar, coder, removefiles.c to a home tar file
localhost - copy the whole /var/www/html subtree to a tar file
all       - execute stuff, extra, desktop and home commands in one go. 
            Use when you want a full backup.
verbose   - display more details about the work being done.
status    - display status info about the stufftarred files on this system.

Also consider backing up Firefox bookmarks, and .emacs config file.
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Figure 1</td>
	</tr>
</table>

<h2>What future improvements do you envisage?</h2>

<p>As a side-effect of writing this article, Iâ€™ve started a â€˜TO DOâ€™ comment section. Currently it does everything I need it to do. Also, despite having written a bash shell script helped by my copy of the Linux Pocket Guide (Oâ€™Reilly) Iâ€™ve never really studied bash. Iâ€™ve just muddled through. I have copies of <em>How Linux Works</em> and <em>The Linux Command Line</em> to make my way through sometime next year â€“ I am concentrating on Ruby this year. The command line options are non-standard but OK for my purposes but could be modified to handle arguments like <code>-f some_kind_of_parameter</code>. There is a UNIX tool called TripWire, used to report changes to folders of files. I think Iâ€™ll be looking at tackling that â€“ in the future.</p>

<h2>A walk through the code (edited highlights)</h2>

<p>The line <code>#!/bin/bash</code> tells Linux that this is a bash shell script. Some people to specify <code>sh</code> instead of <code>bash</code> but as this script is for personal use, Iâ€™m using bash.</p>

<pre class="programlisting">
  #!/bin/bash
  
  # stufftar backup script by Ian Bruntlett, 
  # 2012 - December 2015, expanded and desktar 
  # merged in on August 11th 2012, 
  # March 2013 added &quot;coder&quot; file to Desktop tar,
  # added BACKUP_HOME</pre>
  
<p>As is usual, information about the script is stored at the start of the script (summarised for brevity).</p>

<pre class="programlisting">
  # echo_and_log(logfilename, text to put in log
  # file and echo to screen)
  function echo_and_log()</pre>
  
<p>This is a â€˜helperâ€™ function that echoes its parameters both to the screen and to a specified log file. Useful to avoid repeated identical <code>echo</code> statements.</p>

<pre class="programlisting">
  # if error code set ($1), display error messages
  # and exit programme
  function exit_if_failed()</pre>
  
<p>This is another â€˜helperâ€™ function. It gets passed an error code by its caller. Normally it is 0 so this function does nothing. If it is non-zero then diagnostic information is echoed and it exits/aborts the script with a return code of 1.</p>

<pre class="programlisting">
  # $1 log filename aka $LOG_FILE
  # $2 file to get MD5 from aka $SOURCE_FILENAME
  # example:- get_and_log_md5 &quot;~/md5log.txt&quot;
  &quot;localhost_04_May_2015.tar.gz&quot;
  function get_and_log_md5()</pre>
  
<p>This function calculates the MD5 checksum of the file (function parameter <code>$2</code>) and logs it to a logfile (function parameter <code>$1</code>). It is a â€˜helperâ€™ function used by function <code>perform_backup</code> (Listing 1) when global variable <code>$STUFFTAR_VERBOSE</code> is greater than zero.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
# perform_backup
# $1 - stub of .tar.gz filename
# $2 - name of log file 
# e.g. &quot;scripts/stufftarlog.txt&quot;
# $3 - directory to do the tarring in
# $4 onwards - files/directories to put in .tar.gz
# file relative to $3
function perform_backup()
{
  if [ $# -lt 4  ]
  then
    echo &quot;Error perform_backup() insufficient no of parameters&quot;;
    return 1;
  fi;
 FILENAME_STUB=$1
 DESTINATION_FILENAME=$1`date &quot;+_%d_%B_%Y.tar.gz&quot;`
 LOGFILE=$2
 TAR_DIR=$3

  if [ $STUFFTAR_VERBOSE -gt 0 ]
  then
    echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15} ${16} ${17} ${18} ${19} ${20}
    echo DESTINATION_FILENAME=$DESTINATION_FILENAME e.g. Desktop_28_December_2014.tar.gz
    echo FILENAME_STUB=$FILENAME_STUB
    echo LOGFILE=$LOGFILE
    echo TAR_DIR=$TAR_DIR
  fi
  CURRENT_TIME=`date &quot;+%H:%M:%S&quot;`
  cd $TAR_DIR
  echo_and_log $LOGFILE $CURRENT_TIME Backing up
    key $TAR_DIR $4 $5 $6 $7 $8 $9 ${10} ${11} {12} ${13} ${14} ${15} ${16} ${17} ${18} ${19} ${20}files to $DESTINATION_FILENAME 
  /usr/bin/time -f &quot;%E mins:secs &quot; tar -czf     $DESTINATION_FILENAME $4 $5 $6 $7 $8 $9 ${10} {11} ${12} ${13} ${14} ${15} ${16} ${17} ${18} ${19} ${20}
  exit_if_failed $? &quot;perform_backup to &quot;     $DESTINATION_FILENAME 
  echo File count:-
  tar -tvf $DESTINATION_FILENAME | wc -l
  ls -lh $DESTINATION_FILENAME
  if [ $STUFFTAR_VERBOSE -gt 0 ]
  then
    get_and_log_md5 $LOGFILE $DESTINATION_FILENAME 
  fi
  echo
  cd;
  return 0;
}
# end function perform_backup	
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<p><code>perform_backup</code> is the â€˜engineâ€™ of the script. It validates its parameters. It does some logging, if running in verbose mode. It does the backup using both the <code>time</code> command and <code>tar</code>. The backup is created by <code>tar</code> and <code>time</code> outputs the amount of time taken. It also lists the number of files in the tar file by piping a list of file to the word count utility <code>wc</code>.</p>

<pre class="programlisting">
  # show_last_line
  # $1 is the name to show
  # $2 is the log file to show the tail end of
  # $3 is the number of lines to show </pre>
  
<p>This â€˜helperâ€™ function, <code>show_last_line</code>, echoes some information about a logfile â€“ the name of the archive (â€˜stuffâ€™, â€˜localhostâ€™ etc) and the last <code>$3</code> lines of the log file <code>$2</code>. See Listing 2.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
function show_last_line()
{
  if [ $# -ne 3  ]
  then
    echo &quot;Error show_last_line() insufficient no     of parameters ($#)&quot;;
      echo usage &quot;show_last_line name of file,       source log file, no of lines to show&quot;
    return 1;
  fi;
  echo -n &quot;$1 - $2 &quot;
  tail -$3 $2
  echo -n
  return 0;
}
# end function show_last_line
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>The function in Listing 3 uses <code>show_last_line</code> to display the contents of all <span class="filename">stufftarlog.txt</span> files. The logfile performs two purposes. On the master computer, <code>show_status()</code> indicates when a particular folder was last backed up to tar file. On other computers, it shows the age of the data that has been transferred by tar file.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
function show_status()
{
  echo STUFFTAR STATUS
  show_last_line &quot;Desktop&quot; &quot;$HOME/Desktop/stufftarlog.txt&quot; 3
  echo
  show_last_line &quot;extra&quot; &quot;extra/stufftarlog.txt&quot; 3
  echo
  show_last_line &quot;localhost&quot; &quot;/var/www/html/stufftarlog.txt&quot; 3
  echo
  show_last_line &quot;RPG&quot;   &quot;RPG/stufftarlog.txt&quot; 3 
  echo
  show_last_line &quot;scripts and home&quot; &quot;scripts/stufftarlog.txt&quot; 3
  echo
  show_last_line &quot;stuff&quot; &quot;stuff/stufftarlog.txt&quot; 3
  echo
  return 0;
}
# end function show_status
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 3</td>
	</tr>
</table>

<p>This function, <code>show_status</code>, is triggered when a parameter of <code>status</code> is passed on the command line. It can be used on its own or in conjunction with other commands.</p>

<p>This is the main part of this script. If no parameters are passed, a help message is displayed explaining the use and parameters of the script.</p>

<p>The worker variables <code>BACKUP_DESKTOP</code>, <code>BACKUP_EXTRA</code>, <code>BACKUP_HOME</code>, <code>BACKUP_LOCALHOST</code>, <code>BACKUP_RPG</code>, <code>BACKUP_STUFF</code> are initialised to zero here. Another variable, <code>$STUFFTAR_VERBOSE</code>, is initialised near the start of the script.</p>

<p>Listing 4 is where I loop through the scriptâ€™s command line arguments, setting worker variables accordingly. Note if the parameter <code>all</code> is found, then a bunch of worker variables are set to 1.</p>

&lt;IMAGE xml:link=&quot;simple&quot; href=&quot;Bruntlett-7.gif&quot; show=&quot;embed&quot; actuate=&quot;auto&quot;/&gt;

<p>For information purposes, the name of the script is echoed (<code>$0</code>) and if in verbose mode, <code>ls -lh</code> is used to show even more information about the script file. Also for information purposes, the status of worker variables is displayed.</p>

<pre class="programlisting">
  echo $# PARAMETER\(S\),
  BACKUP_STUFF=$BACKUP_STUFF
  BACKUP_EXTRA=$BACKUP_EXTRA,
  BACKUP_DESKTOP=$BACKUP_DESKTOP,
  BACKUP_HOME=$BACKUP_HOME,
  BACKUP_RPG=$BACKUP_RPG,
  BACKUP_LOCALHOST=$BACKUP_LOCALHOST,
  STUFFTAR_VERBOSE=$STUFFTAR_VERBOSE,
  STUFFTAR_STATUS=$STUFFTAR_STATUS</pre>
  
<p>For consistency, the script changes the current directory to the current userâ€™s home directory before doing any file handling.</p>

<pre class="programlisting">
  cd ~</pre>
  
<p>Then the .tar.gz files are created â€“ basically checking to see if a worker variable is 1 and then calling <code>perform_backup</code> to do the work.</p>

<pre class="programlisting">
  # backup to a stuff tar
  if [ $BACKUP_STUFF -eq 1 ]
  then
    perform_backup &quot;Stuff&quot; &quot;stuff/stufftarlog.txt&quot;
    &quot;$HOME&quot; &quot;stuff&quot; 
  fi</pre>
  
<p>Similar clauses are used for the creation of the extra, rpg, desktop .tar.gz files. Backing up the key â€˜homeâ€™ files is a little different:</p>

<pre class="programlisting">
  # backup key /home/ian things e.g this backup
  # script to a tar file
  if [ $BACKUP_HOME -eq 1 ]
  then
    perform_backup &quot;Home&quot; &quot;scripts/stufftarlog.txt&quot;
    &quot;$HOME&quot; refurb scripts synclamp stufftar coder
    removefiles.c;
  fi</pre>
  
<p>And localhost is used to backup key LAMP files (see Listing 5).</p>

&lt;IMAGE xml:link=&quot;simple&quot; href=&quot;Bruntlett-8.gif&quot; show=&quot;embed&quot; actuate=&quot;auto&quot;/&gt;

<p>As its final act, if the â€˜statusâ€™ option has been activated, the status of every backup file is displayed.</p>

<pre class="programlisting">
  if [ $STUFFTAR_STATUS -eq 1 ]
  then
    show_status;
  fi</pre>
  
<p>And that is it.</p>

<h2>Feedback from Overload technical reviewers</h2>

<p>This script serves as a decent example of how to back things up in a reproducible way using tar. I didnâ€™t see any glaring errors in it, but I would comment that it is not tolerant of spaces in filenames (fixing that would require liberal use of double-quotes, and I usually find some trial-and-error is required to get this right).</p>

<p class="blockquote">The script was written by me â€“ a bash novice. Given the importance of the data, it was tested heavily as it evolved. As I expected to use the resulting .tar.gz files from the command line, I decided that my filenames would not contain spaces.</p>

<p>The article as it is now is a bit specific to one use case â€“ I think it would be more useful if it explained the ideas and techniques being used rather than presenting the details of the script itself. E.g.:</p>
<ul>
	<li>Interesting policy decisions like creating separate log files for each piece of work being done â€“ it would be interesting to hear how this supports the workflow.
	
		<p class="blockquote">I thought about having a single log file, <span class="filename">~/stufftarlog.txt </span>but it wasnâ€™t flexible enough and Iâ€™d have to somehow process that log file, looking for status information about each type of backup. By having separate log files, I avoid that problem and it means I can decide to just backup certain bunches of files instead of a full-blown backup of everything.</p></li>
	
	<li>How to get the last relevant line out of a log file (as the script does) â€“ this seems more widely-applicable and a useful little nugget.
	
		<p class="blockquote">I added the function body of <code>show_last_line</code> to this article. It is quite simple and uses the <code>tail</code> command.</p></li>
		
	<li>How to deal with command line arguments (the for loop used here looks quite convenient for simple applications like this).
		
		<p class="blockquote">Yes. With a bit of effort it can be more flexible. At the moment it handles one word parameters that act as flags or specify a certain backup to perform.</p>
		
		<p class="blockquote">Supporting a syntax like <code>-f some_kind_of_flag</code> would be possible. I have some ideas about it, mainly involving extending the loop to set a flag (<code>$ARGUMENT_F_EXPECTED</code>) when a parameter of <code>-f</code> is detected and setting a flag. Then the head of the loop would need another set of <code>if</code> statements â€“ followed by use of the <code>continue</code> loop modifier.</p></li>
		
	<li>The benefits of writing a script rather than doing this manually (e.g. reduced errors and less time take)

		<p class="blockquote">Spot on. Being able to run a command to do all the backups I wanted, have standard filenames and contents, and walk away was crucial. That dealt with errors during creation of the backups. However, I used to transport my files to a Samsung NC10 NetBook (when it wasnâ€™t being wiped and used to test Lubuntu pre-releases), and I noticed that I was occasionally forgetting to install the contents of newer .tar.gz files. So I needed to know when a particular folderâ€™s files were created. This resulted in the function <code>show_last_line</code> (it can show more than one line) which was discussed earlier. When Iâ€™m working on the Samsung NC10, typing in <code>./stufftar status</code> means I can see how fresh this copy of my files is.</p></li>

</ul>

<h2>Reference</h2>

<p>stufftar can be downloaded from:<a href="https://sites.google.com/site/ianbruntlett/home/free-software/linux">https://sites.google.com/site/ianbruntlett/home/free-software/linux</a></p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
