Archive for the 'Shell' Category

I created this Bash script as a project for the system administration course I’m taking for the summer. I’m sure there are bugs in it, so let me know if you find any.

It basically uses an XML configuration file, which includes the source, destination, and any excludes from the transfer. You then pass either -u or -d (upload or download) and the options -x (delete if not in source) and -f (force). Destination can be local or remote, but source must be local.

Here is the code:

#!/bin/bash
## Transfer Script
## By David Drager
## CSC586: Summer II 2008
## Requires: xml2, rsync

## Settings
tempdir="/tmp/"
rsynccommand="/usr/bin/rsync"

## Usage command
usage="usage: transfer.sh [options] <config-file>.xmlnoptions:n  -d or -u:t download or upload, resp. one and only one must be presentn  -f:ttforce transfer regardless of 'newness' of filen  -x:ttdelete items in target not present in source"

# Check to make sure temporary directory exists
[ -d $tempdir ] || { echo -e "Error: Could not locate a temporary directory. See file settings."; exit 1; }

# Usage Command
[ $# -eq 0 ] && { echo -e "ERROR: Needs at least the -d or -u flag plus a config file.nn$usage"; exit 1; }

## Get options passed to the program
while getopts "dufx" flag
do
  [ "$flag" = "?" ] && echo -e "ERROR: Flag(s) not valid.nn$usage" && exit 1;
  eval "opt_$flag=1"
done
shift $((OPTIND-1))
configfile="$1"

if [ "$opt_d" = 1 ] && [ "$opt_u" = 1 ]
then
  echo -e "Error: Use either -u Upload or -d Download, but not bothn$usage"; exit 1;
elif  [ "$opt_u" = "" ] && [ "$opt_d" = "" ]
then
    echo -e "Error: Use either -u Upload or -d Download, but not bothn$usage"; exit 1;
fi

if [ "$opt_f" = 1 ]; then
  force=1
fi

if [ "$opt_x" = 1 ]; then
  deltar=1
fi

## Make sure config file is located
if [ "$configfile" != "" ]
then
  [ -f "$configfile" ] || { echo -e "Error: Config file not found.n$usage"; exit 1; }
else
   echo -e "Error: Config file not specified.n$usage"; exit 1;
fi

## End of swich verification

# echo Action: "$action"
# echo Force: "$force"
# echo Delete Target Files: "$deltar"
# echo Config: "$configfile"

## Now read config file

## Set temp file for XML parsing
tempfile="$tempdir"transferscript_$$
tempexcludes="$tempdir"transferscriptexcludes_$$
# echo -e "Temp:$tempfile"

# Run config file through xml2
xml2 < "$configfile" > "$tempfile"

[ -f "$tempfile" ] || { echo -e "There was a problem processing the XML file."; exit 1; }

# Make sure that source and destination are found
excludelist=""
while read line; do
    key=$(echo $line | awk -F '=' '{print $1}')
    value=$(echo $line | awk -F '=' '{print $2}')
    if [ "$key" = "/sync/@src" ]; then
      source="$value";
    elif [ "$key" = "/sync/@dst" ]; then
      destination="$value"
      # Add any exclude options to array
    elif [ "$key" = "/sync/exclude" ]; then
      tempexcl=("$value")
      excludelist=("${excludelist[@]}" "${tempexcl[@]}")
    fi
done < "$tempfile"

[ "$source" ] || { echo "Error: Config file must include a source"; exit 1; }
[ "$destination" ] || { echo "Error: Config file must include a destination"; exit 1; }

source="$source/"
destination="$destination/"

[ -d "$source" ] || { echo "Error: Source must be a local directory"; exit 1; }

excludes=""
excludes=${excludelist[@]}

# echo Excludes: "(${#excludelist[@]}): $excludes"

## Clean up temp file from xml process
rm "$tempfile"

## Build up the command line

[ -f "$rsynccommand" ] || { echo -e "Error: Could not locate rsync command."; exit 1; }

fullcommand="$rsynccommand"
fulltestcommand="$rsynccommand"

if [ "$opt_f" == "1" ]
then
    fulltestcommand="$fulltestcommand -nva"
    fullcommand="$fullcommand -a"
else
    fulltestcommand="$fulltestcommand -nvau"
    fullcommand="$fullcommand -au"
fi

if [ "$opt_u" == "1" ]
then
  fileorder="$source $destination"
  echo "Evaluating transfer from $source ==> $destination"
elif [ "$opt_d" == "1" ]
then
  fileorder="$destination $source"
  echo "Evaluating transfer from $destination ==> $source"
fi

[ "$opt_x" == "1" ] && { fulltestcommand="$fulltestcommand --delete"; fullcommand="$fullcommand --delete"; }

## Move exclude list to a file.
## This duplicates as above but I originally thought we were passing it to rsync as a list and not as a file.

[ "${#excludelist[@]}" -gt 0 ] && {
    tempfile="$tempdir"transferscript_$$
    touch "$tempfile"
    echo "$excludes" | tr " " "n" > "$tempfile"
    fulltestcommand="$fulltestcommand"" --exclude-from=$tempfile"
    fullcommand="$fullcommand"" --exclude-from=$tempfile"
}

fulltestcommand="$fulltestcommand $fileorder"
fullcommand="$fullcommand $fileorder"

# We only want lines minus top line and bottom 3 lines
testresult=`$fulltestcommand | tail --lines=+2 | head --lines=-3`

# If this is empty, then notify that no files would be transferred.
 [ "$testresult" ] || { echo "This command would not transfer any files. Script exiting."; rm "$tempfile"; exit 1; }

# Display changes
echo -e "Changes to be made:n--------------------n$testresultn--------------------"

# Check to see if we really want to run the command.
echo "Do you wish to perform this command? $fullcommand (y/n)[y]"
read confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "" ]
then
    echo "Performing transfer..."
    # Without -v this will not output anything.
    $fullcommand
    echo "Transfer complete."
    rm "$tempfile"
else
    echo "Cancelling transfer..."
    rm "$tempfile"
fi

exit 0

Here is the sample config file:

<sync src="/home/dir/bash-prog/dir1/" dst="login@some.machine:/home/dir/dir2">
        <exclude>
          .test3
          another.*
        </exclude>
</sync>

Windows lacks the linux ’shutdown’ command, so it is a pain to get it to schedule a reboot in the future. Linux’s shutdown command make this easy, just issue the command ’shutdown -r +60′ for example to reboot an hour in the future.

No such luck in Windows, you need to download a separate program to do this. It is a sysinternals program, you might remember sysinternals from such utilies like FileMon and ProcessMonitor.

The program we use for this is called PsTools and more specifically the file psshutdown.exe.

[Download PsTools here]

Place psshutdown.exe into a directory for future use, for this example we will use c:\tools\.

Then open a command prompt and type the following command:

at 2:00am c:\tools\psshutdown.exe -r -f -c -t 10 /accepteula

This will result in:

Added a new job with ID = 1

You can verify this task has been added by looking at the Scheduled Tasks - the job name will be At1 if you haven’t scheduled any other tasks via the command line.

If all goes will, Windows will reboot at 2:00am, or your specified time.

Wow - I get so frustrated when I try to copy some files over old ones and I get:

[root@server1 wordpress]# cp -Rf * ../public_html/
cp: overwrite `../public_html/license.txt'? y

-R is recursive, but -f is supposed to copy over without confirmation. What could it be?!

Check out your alias command using ‘alias’:

[root@server1 wordpress]# alias
alias cp='cp -i'

Sure enough - alias is set on Redhat Based systems into -i, or interactive mode. Remove this alias with ‘unalias cp’ and it will be removed.

Happy copying!

In case you were wondering, I just invented the phrase PVPN - Personal Virtual Private Network.

I use Hamachi to connect my work, home and laptop PCs and I’ve found it invaluable over the past few years for a number of reasons. Music over VPN, Remote Desktop/VNC over VPN, and more. So now, I’d like to join my N800 to this growing network to make easy and secure access and file transfer wherever I am connected.

Fortunately the folks at Logmein have compiled a client for the N770, and this also works on OS2008 on the N800 (Let me know on the N810).

This is an alternate take on the wiki article at Logmeinwiki.

Note: For the commands below I will have assumed that you have already installed the openssh server so you can access the N800 via an SSH client with root access. You can also use the built in Xterm and gainroot but it is a pain in the ass typing all of those commands in via the touchpad. If you are using gainroot some of the directories below will change, for example Hamachi will install in /home/user/.hamachi instead of /root/.hamachi. Also I downloaded the client to my memory card in /media/mmc2/ but you can put it anywhere.

Your login should look like this:

BusyBox v1.6.1 (2007-09-27 18:08:59 EEST) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

Nokia-N800-51-3:~#

Make sure wget is installed:

apt-get install wget

Make to get the latest Logmein Client from http://files.hamachi.cc/linux/nokia-770/.

Just follow my process below for installing the Hamachi client and joining your network.

Nokia-N800-51-3:/media/mmc2/tmp# wget http://files.hamachi.cc/linux/nokia-770/hamachi-0.9.9.9-20-lnx-n770.tar.gz
--10:31:47-- http://files.hamachi.cc/linux/nokia-770/hamachi-0.9.9.9-20-lnx-n770.tar.gz
= `hamachi-0.9.9.9-20-lnx-n770.tar.gz'
Resolving files.hamachi.cc... 72.5.76.16
Connecting to files.hamachi.cc|72.5.76.16|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 116,020 (113K) [text/plain]

100%[==========] 116,020 256.95K/s

10:31:48 (256.33 KB/s) - `hamachi-0.9.9.9-20-lnx-n770.tar.gz' saved [116020/116020]

Nokia-N800-51-3:/media/mmc2/tmp# tar zxvf hamachi-0.9.9.9-20-lnx-n770.tar.gz
hamachi-n770-0.9.9.9-20/
hamachi-n770-0.9.9.9-20/LICENSE
hamachi-n770-0.9.9.9-20/README
hamachi-n770-0.9.9.9-20/LICENSE.tuncfg
hamachi-n770-0.9.9.9-20/LICENSE.openssh
hamachi-n770-0.9.9.9-20/LICENSE.openssl
hamachi-n770-0.9.9.9-20/hamachi
hamachi-n770-0.9.9.9-20/tuncfg/
hamachi-n770-0.9.9.9-20/tuncfg/Makefile
hamachi-n770-0.9.9.9-20/tuncfg/tuncfg.c
hamachi-n770-0.9.9.9-20/tuncfg/tuncfg
hamachi-n770-0.9.9.9-20/CHANGES
hamachi-n770-0.9.9.9-20/install
Nokia-N800-51-3:/media/mmc2/tmp# cd hamachi-n770-0.9.9.9-20/
Nokia-N800-51-3:/media/mmc2/tmp/hamachi-n770-0.9.9.9-20# sh install

install: line 7: HAMACHI_DST: not found
Copying hamachi into ..
Creating hamachi-init symlink ..
Copying tuncfg into /sbin ..

Hamachi is installed. See README for what to do next.

Nokia-N800-51-3:/media/mmc2/tmp/hamachi-n770-0.9.9.9-20#
Nokia-N800-51-3:/media/mmc2/tmp/hamachi-n770-0.9.9.9-20# cd
Nokia-N800-51-3:~# tuncfg
Nokia-N800-51-3:~# hamachi-init
Initializing Hamachi configuration (/root/.hamachi). Please wait ..

generating 2048-bit RSA keypair .. ok
making /root/.hamachi directory .. ok
saving /root/.hamachi/client.pub .. ok
saving /root/.hamachi/client.pri .. ok
saving /root/.hamachi/state .. ok

Authentication information has been created. Hamachi can now be started with
'hamachi start' command and then brought online with 'hamachi login'.
Nokia-N800-51-3:~# hamachi start
Starting Hamachi hamachi-lnx-n770-0.9.9.9-20 .. ok
Nokia-N800-51-3:~#

Hamachi is now running on our little tablet!

But it has not joined our network at this point, so we follow the logmein Hamachi documentation to do so.

Nokia-N800-51-3:~# hamachi set-nick DaveN800
Setting nickname .. ok
Nokia-N800-51-3:~# hamachi login
Logging in ....>....... ok
Nokia-N800-51-3:~# hamachi join YourNetwork
Password:
Joining YourNetwork .. ok
Nokia-N800-51-3:~# hamachi go-online YourNetwork
Going online in YourNetwork .. ok
Nokia-N800-51-3:~#

And now…checking other Hamachi clients, shows our little device is online!

hamachi on n800

Now we need to tell our tablet to put hamachi online whenever we restart the system and also set the keepalive lower.

To lower the keepalive:

Nokia-N800-51-3:~/.hamachi# echo "KeepAlive 20" >> ~/.hamachi/config

This is all great, and you should be online now. But you would need to start Hamachi on every reboot which isn't going to cut it. We will add the Hamachi start process to the init scripts. Add the following lines to the file '/etc/init.d/rcS' right before the line which says 'exit 0'

<code>/sbin/tuncfg;/usr/bin/hamachi -c /root/.hamachi start

In order to do this, use VI.

vi /etc/init.d/rcS

  • Press capitol ‘G‘ to scroll to bottom of the file
  • type ‘i‘ to enter insert mode
  • hit up a few times to a blank line before exit 0, or hit enter at the beginning of the line to create a new line.
  • Paste the above line into the file
  • Press “esc” using the special xterm button, or hit escape if you are using ssh.
  • type “:wq!” — this command enters the command, mode, tells it to write the file, then quit and execute

That should be all you need! Power off the N800 and power it back up. After restarting your N800 you should see it connect to your PVPN Hamachi network and be online!

Let me know if you have any problems or comments about the above installation procedure!

This simple linux bash script will delete subdirectories in a directory based on when the subdirectory was last modified.

In my sample script, it looks in the directory /home/backup and deletes any directories older than 7 days. Replace 7 with the number of days of your choosing!

for i in `find /home/backup/ -maxdepth 1 -type d -mtime +7 -print`; do echo -e "Deleting directory $i";rm -rf $i; done

Just to explain:

  • -maxdepth 1 = list only files/directories in 1 level from main search directory
  • -type d = list only directories
  • -mtime +7 = modified time of more than 7 days
  • -print = print out list; so we can then process the list with our bash script

This is useful for backup programs which do not clean up their old backups. Let me know if you have any questions or comments!

Technorati Tags: ,

This seems like a pretty rare bug but annoying anyway. On my system I found that when logrotate would run, some log files such as /var/log/maillog did not rotate properly.

Typically, logrotate works like

Write to <tag>maillog</tag>
Daily, move maillog to maillog.1
Daily, move maillog.1 to maillog.2
etc...

However it was going

Write to maillog,
Daily, move maillog to maillog.1, keep writing to maillog.1
Daily, move maillog.1 to maillog.2, keep writing to maillog.2
etc.

According to this bug tracker entry and this post, it is a problem with the version of logrotate, and people having the /tmp directory on a separate mount (I did not even have mine set to noexec like I should have, and I still had this problem [fixed now, by the way]).

It is easily fixed by installing the version of logrotate from the CentOS fasttrack repository [link]. After installing this, it looks like logrotate is rotating the log files correctly.

This is a pretty simple thing to do, once you’ve figured it out. You attach files using the following syntax:

uuencode filename1 filename2|mail user@domain.name

This will uuencode the file names, then pipe the output to the mail command, and mail to the user.

If you try to make or install a program and you receive an error like this:

make[2]: cc: Command not found

Then that means you don’t have a C+ compiler installed!

If you are using centOS or other yum based distro, type:

yum install gcc-c++

That will install the needed RPMs for you.

I recently had a problem where my Spamassassin install started thinking that a lot of spam messages were really ham (non-spam). Since these were getting BAYES_00 scores of -2.5 they were almost all getting through my spam filter. These particular messages all were regarding STOCK quotes and were pretty obviously spam just by looking at the text of the messages. Somehow my Spamassassin install thought that they were not spam because the messages were being passed as ham by the Bayesian filter. Since they kept getting past, the bayesian filter kept learning them as HAM.

In order to break this vicious cycle, you just need to clear out the bayesian tokens. It’s very easy to do. As root user, type:
sa-learn --clear
This starts you fresh. By default, Spamassassin won’t use the bayes filter until it has 200 spam and ham messages, so until you get to that level it will continue to learn based the other Spamassassin detection settings.

Ideally, I would have sa-learn train using these spam messages. But since I use Outlook, and there is no “easy” way to have it interface with sa-learn, I find it easier to clean out the bayes tokens every once in a while. SpamAssassin Coach is a plugin for outlook which should connect to your spamd server and “learn” a message as ham or spam. But in practice, it did not work for me. It looks like the project has a lot of potential.

For more information on how Bayesian filtering works, check out this wikipedia article.

Technorati Tags: , ,

If you or your client is using an old-DOS based program to do work (for example, Wordperfect for DOS) - and you need to print to a printer which is shared on the network, you first need to map the printer to an LPT port. You do this by using the following command in a dos prompt (Start -> Run -> cmd):

net use lpt3 \\SERVER_NAME\PRINTER_NAME

You can then set up your dos program to print to lpt3 and it will be sent to that printer. To print right from the command line, you could use the following syntax:

copy c:\test.txt lpt3

Technorati Tags: , , ,
  • Welcome to systemBash, a technology and system administration blog by David Drager. If you enjoy this sort of content, can can subscribe to the RSS using the link to the right.