Oxaric’s Blog

A compendium of amazing things…

Posts Tagged ‘Linux’

Make A BASH Script Globally Executable

Posted by oxaric on December 4, 2008




Bash scripts are great! They make life a lot easier. But they can be a pain to drag around using mv and cp to get them to the right directory so you can execute them directly using: ~$ ./myscript.sh. Thankfully there is a much better way to run often used Bash scripts.


First, before we start you need to make sure the Bash script you’re interested in is executable. To be executable the script file needs the proper permission to run on your system. The command needed to give a file permission to run is chmod +x followed by the name of your script file.


This looks like:

~/test> chmod +x myscript.sh



Once your script is executable you need to copy it to a directory that your system expects to contain executable scripts and code. On most systems you will have a choice between two directories. If you are the only user of your system you can cpy your script to either /usr/bin or /usr/local/bin. If you share your system with other people it’s best to copy your script to /usr/local/bin. You will most likely need super-user privileges to copy your script to either of these directories so you’ll most likely need to use the sudo command or an equivalent. The sudo command will give you temporary super-user privileges and allow you to copy the script. Now you can directly copy the script into one of the stated directories but it is my preference to remove the .sh from my script file names before copying them.


Here are two script file copy examples:

~/test> sudo cp myscript.sh /usr/bin/myscript
~/test> sudo cp myscript.sh /usr/local/bin



Once you copy your script file it will be executable from any directory in your system. Simply type the name of your script file, hit enter, and your script will execute. Give it a try!

Posted in BASH, Linux, Tips | Tagged: , , , , , , , | Leave a Comment »

Quick BASH Script For Easier PHP Execution

Posted by oxaric on December 4, 2008




If you’re not running a web server, such as Apache, you might find PHP script can be a bit annoying to run. First you write your .php script, save the file, run the file through PHP, save the output into an .html file, and finally open the .html file in your preferred browser.


In order to simplify the steps needed to view the results of your .php script I created the Bash script below to automate some of the intermediary steps. The script takes the filename of a .php script, runs it through PHP, saves the resulting .html code as filename.html, and then opens the html file in Firefox.


Example:

~/test> ./runphp.sh myscript.php


Click to directly download runphp.sh


# Louis Casillas, oxaric@gmail.com
# Usage:
#       ~$ ./runphp.sh myphpfile.php


# Takes a php filename and executes the php code which
# creates html code.  Saves the resulting html code 
# into filename.html and opens the html file with
# Firefox.


# Assumes you have a version of php and firefox  
# installed on your system


if [[ "$1" == "" ]]; then
   echo
   echo "Specify a php filename"
   echo


   exit
fi


php_filename="$1"
php_filename_size=${#php_filename}
period_position=-1


# search for the last period in the passed filename
for ((i=$php_filename_size;i>=0;i+=-1)); do


   if [[ "${php_filename:$i:1}" == "." ]]; then
      period_position=$i
      break;
   fi
done


# if the passed filename contains a period then erase the
# file extension and add .html to the filename
if [ $period_position -eq -1 ]; then
   html_filename="$php_filename"".html"
else
   html_filename="${php_filename:0:$period_position}"".html"
fi


# run the php code and store the resulting html code
php $php_filename > $html_filename


# open the html file in firefox
firefox $html_filename

Posted in BASH, Linux, PHP | Tagged: , , , , , , , , , | Leave a Comment »

Fun With BASH Piping!

Posted by oxaric on November 24, 2008

You may or may not be familiar with piping but if you use or plan to use a Linux machine you should definitely look into it.


Piping allows a command to send it’s output to another command. If you are familiar with programming you could think of this situation as calling a function, getting the output, and sending it directly to another function. Below are examples of two different forms of piping.


These are the commands I’ll use in the examples:


ls – lists all of the files in the current directory, Windows users might know this as the dir command


find – when used with no parameters it will list every file inside the current directory including files inside of other directories


rm – deletes a file, Windows users might know this is as the del command


grep – searches a string looking for a given string or pattern





Piping Example



~/test> ls | grep a.out


What happens:

First, the ls command will find and try to display all the files in the current directory. However, the bar symbol | causes the ls output to be piped to the grep command. The grep command will then take the input from the pipe and search the piped lines for any string that contains “a.out“. If grep finds any such strings it will then directly display them.


Using the bar symbol, |, is the most common form of piping. But another form of piping exists called substitution piping.


Substitution piping can be used with commands that do not work with the direct piping method shown above. An example of such a command is rm which will not accept a direct piping of file names or directories to delete. The rm command only accepts file names and directories if they are directly given in it’s parameters while calling it. This is the beauty of substitution piping. It allows you to perform a command and send the output line-by-line as a parameter to another command.


Substitution Piping Example




~/test> rm $(find | grep a.out)


What happens:

First, the commands inside of $() will run and produce a list of all files in the current directory and in any directories inside the current directory that have “a.out” in their file name. As you can see, both forms of piping can be used together. Once the commands inside the substitution pipe are completed the output will be passed line-by-line as a parameter to the first command rm which will delete every file passed to it.





Caveat emptor!
Be careful!



Piping can be a force for good and evil. It is extremely easy to be mistaken about the exact output of a command and end up deleting precious files or doing all sorts of crazy things. Test all of your commands before piping.

And remember, a wise old man once said, “To use commands is human, to pipe divine.” ;)

Posted in Linux, Tips | Tagged: , , , , , , | 2 Comments »

3 Simple C++ String Functions

Posted by oxaric on November 23, 2008

Here are some simple C++ functions I thought I’d put up. Maybe I’ll put up more later.


The 3 functions are:
string trim( string line );
string prepareLineForLinux( string line );
bool isWhiteLine( string line );


trim()
input: receives a string
output: returns a new string with all leading and ending whitespace removed


prepareLineForLinux()
input: receives a string
output: returns a new string that will be acceptable to be used in a Linux system call. Checks for Linux special characters and includes the necessary delimiters.


isWhiteLine()
needs the function trim()
input: receives a string
output: returns true if the string is empty otherwise false


Click to directly download stringfunctions.cpp

// filename 'stringfunctions.cpp'
// Use: Has some functions used for manipulating strings
// By: Louis Casillas, oxaric@gmail.com

#include <iostream>
#include <string>

using namespace std;

string trim( string line );
string prepareLineForLinux( string line );
bool isWhiteLine( string line );

// needs the function trim()
// input: receives a string
// output: returns true if the string is empty otherwise false
bool isWhiteLine( string line )
{
   string temp = trim(line);

   if ( (temp == "") || (temp == "\n") )
   {
      return true;
   }
   else
   {
      return false;
   }
}

// input: receives a string
// output: returns a new string with all leading and ending whitespace removed
string trim( string line )
{
   if ( line.empty() )
   {
      return "";
   }

   int string_size = (int)(line.length());
   int beginning_of_string = 0;

   // the minus 1 is needed to start at the first character
        // and skip the string delimiter
   int end_of_string = string_size - 1;
   
   bool encountered_characters = false;
   
   // find the start of chracters in the string
   while ( (beginning_of_string < string_size) && (!encountered_characters) )
   {
      // if a space or tab was found then ignore it
      if ( (line[ beginning_of_string ] != ' ') && (line[ beginning_of_string ] != '\t') )
      {
         encountered_characters = true;
      }
      else
      {         
         beginning_of_string++;
      }
   }

   // test if no characters were found in the string
   if ( beginning_of_string == string_size )
   {
      return "";
   }
   
   encountered_characters = false;

   // find the character in the string
   while ( (end_of_string > beginning_of_string) && (!encountered_characters) )
   {
      // if a space or tab was found then ignore it
      if ( (line[ end_of_string ] != ' ') && (line[ end_of_string ] != '\t') )
      {
         encountered_characters = true;
      }
      else
      {         
         end_of_string--;
      }
   }   
   
   // return the original string with all whitespace removed from its beginning and end
   // + 1 at the end to add the space for the string delimiter
   return line.substr( beginning_of_string, end_of_string - beginning_of_string + 1 );
}

// input: receives a string
// output: returns a new string that will be acceptable to be used in a Linux system call
//         checks for Linux special characters and includes the necessary delimiters
string prepareLineForLinux( string line )
{
   string return_string = "";
   
   int i = 0;
   int string_size = (int)(line.size() - 1);
   while ( i <= string_size )
   {
      if ( line[i] == ' ' )
      {
         return_string += "\\ ";
      }
      else if ( line[i] == '\'' )
      {
         return_string += "\\\'";
      }
      else if ( line[i] == '\\' )
      {
         return_string += "\\\\";
      }
      else if ( line[i] == '(' )
      {
         return_string += "\\(";
      }      
      else if ( line[i] == ')' )
      {
         return_string += "\\)";
      }
      else if ( line[i] == '[' )
      {
         return_string += "\\[";
      }      
      else if ( line[i] == ']' )
      {
         return_string += "\\]";
      }
      else if ( line[i] == '&' )
      {
         return_string += "\\&";
      }
      else
      {
         return_string += line[i];
      }

      i++;
   }
         
   return return_string;
}

int main()
{
   cout << "\ntrim() function\n---\n";

   string test1 = \t  Hello World!\t \t ";
   cout << "\nOriginal Text: |" << test1 << "|\n";
   cout << "Trimmed Text: |" << trim(test1) << "|\n";

   cout << "\nprepareLineForLinux() function\n---\n";
   string test2 = "mv /this is/ my/ directory[0]/file-(4).txt";

   cout << "\nOriginal Text: |" << test2 << "|\n";
   cout << "Prepared Text: |" << prepareLineForLinux(test2) << "|\n";
   
   cout << "\nisWhiteLine() function\n---\n";

   string test3 = " ";
   cout << "\nOriginal Text: |" << test3 << "|\n";
   cout << "isWhiteLine?: " << isWhiteLine(test3) << " <--- 0=NO, 1=YES \n";

   return 0;
}

Posted in C/C++, Linux, Programming | Tagged: , , , , , , , , , , , | Leave a Comment »

Linux BASH Aliases

Posted by oxaric on November 17, 2008

If you use bash then right now you can create aliases. An alias allows you to define a command that will call another command that is much longer or doesn’t automatically have the options you want.


If you want to list all of the files in your current directory you would use the command "ls". However, this command by itself will not show you hidden files. In Linux any file that starts with a period “.” is considered a hidden file. If you want to see all the files in your current directory including normal and hidden files you would need to use the command "ls -A".


Typing "ls -A" a few times isn’t such a big deal but if you are constantly using this command it would be quicker to create a bash alias. To create a bash alias we use the command “alias”. Makes sense huh? :)


Here is the basic format for the alias command:
alias new_command_name='old_command -plus_the_options_you_want'


NOTE: The new command name does not have any quotes around it but the old command with the added options has single quotes around it.


To make an alias for "ls -A" you need to type the following in your bash shell:

~/test> ls alias ls=’ls -A’ grep a.out



Once you’ve typed this line hit enter and the alias is created. Now during your current bash session if you want to see both the hidden and normal files in your current directory you only need to type "ls".


But wait!



If you create an alias manually like above you will lose all your aliases when you close the bash shell. If you want these aliases to be a permanent feature of your bash shell you need to do two things.

  1. Add the following line to your "~/.bashrc" file:
    if [ -f ~/my_bash_additions ]; then
       . ~/my_bash_additions
    fi



    NOTE: To edit this file you will need to be root or use "sudo".

  2. Create a file in ~/ called “my_bash_additions” and put your alias commands into this file.



Once you’ve done this all that’s left is to restart your bash shell. All of your aliases will be saved and ready for use. If you typed any commands wrong or anything is amiss you will probably get an error message when your bash shell is loading. If you get any errors go back into your “my_bash_additions” file, fix the errors, and re-start your bash shell. But I’m sure you’ll never make any mistakes so you’ll never have to do this. :)


Extra



Another cool thing you can do with your bash shell is to edit the way your command prompt looks. You can make your prompt colorful, plain, add extra information such as the current time, lots of stuff.


Here is a site with good information about editing your command prompt.


I’ve uploaded my own “my_bash_additions” file. Feel free to download it and try it out. It has a lot of features I like. It doesn’t have too many comments but it shouldn’t be too hard to understand.


Click to directly download my_bash_additions

Have fun playing!

Posted in BASH, Linux, Tips | Tagged: , , , , , , , | Leave a Comment »

Automated Harddrive Mounting Script

Posted by oxaric on November 15, 2008

I have 2 big 500 GB harddrives in USB cases with 3 partitions per drive. When they are connected to my machine the system automatically mounts them to /media and this seems great in theory. I only noticed something annoying after the drives laid idle for a while. My machine would quietly lose touch the drives and their files would no longer be accessible. However, the partition names would still remain in /media becoming ghost partition points.


If I accessed either drives after they had gone to sleep they would be mounted again but because the first mount points were still in /media my system seemed to like to randomly append an ‘_’ to the names of the mount points… sometimes… when it felt like it. The problem with this is that if anything running on my machine was looking for ‘/media/my_usb_drive’ it might find this mount point but because it is has become a ghost mount point the program will find nothing inside. The real drive would now be mounted to ‘/my_media/usb_drive_’.


So I created a script to deal with automatically finding the drives attached to my computer and mounting them to permanent mount points I created in /mnt. The mount points are simply directories I created in /mnt for the sole purpose of being a permanent home for my drive partitions. Now if the drives go to sleep I can simply run this script file and it will wake up the drives that are sleeping and mount them in their proper place in /mnt.


The benefit of this is that I no longer have to worry about having ghost mount points and I can use absolute file paths with no problems. Also, if I unplug and plug back in one of the drives I run this script and it automatically finds the correct /dev location of the drive and mounts it for me.


The script is fairly simple and contains enough comments that it should be fairly easy to edit it for your own needs. It is currently setup for my own system. Also, notice this program does not need to be used just with USB drives. Any drive type will work.


An extra tip


If you really hate to have your drives fall asleep you can directly edit your cron job process by using “crontab -e” and adding the line for each partition or drive:
“0 1 * * * ls /path_to_drive/my_mount_point”


The cron job process executes a command at a specific time like 1 AM for a system backup or at set time interval like every hour. Adding the above will tell the cron job to poke your drives every hour to keep them awake. Although if you don’t have a serious reason for using this you’ll save energy and have happier drives by letting them fall asleep. :) You could also setup cron to execute this script every so often just to make sure you’ll definitely keep your drives awake and mounted properly.


Click to directly download mount-usb-drives.sh

#!/bin/bash
# file name 'mount-usb-drives.sh'
# coded by: Louis Casillas, e-mail: oxaric@gmail.com

# Below are the physical IDs of the drives
# To see this run: $ sudo fdisk -l
# look at Disk identifier:

# ID: USB DRIVE: S_DRIVE
S_ID=0x44fdfe06

# ID: USB DRIVE: P_DRIVE
P_ID=0x9a4c35e6

# My USB drives are FAT32 so they use the vfat format to be mounted
MY_FILE_FORMAT="vfat"

# this is my user ID
# To see this run: $ id
MY_USER_ID=1000

total_max_drives_to_find=2 # number of USB drives I have
number_of_drives_found=0

echo
echo "Attempting to locate connected drives..."

# grabs a list of all the drives connected to the machine
sudo fdisk -l | column > /tmp/current_drives_connected.txt

# setup the input so the while loop will read every
# line from the file 'current_drives_connected.txt'
exec< "/tmp/current_drives_connected.txt"

# remove the temp file
rm /tmp/current_drives_connected.txt

while read line
do
    # takes the current line and looks for the physical ID
    # of the S_DRIVE
    test="$(echo "$line" | grep "$S_ID")"

    # if the ID was found then attempt to mount the drives
    if [[ "$test" != "" ]]; then

        number_of_drives_found=$(( $number_of_drives_found + 1 ))

        echo
        echo "S_DRIVE FOUND!"
        echo "Attempting to mount S_DRIVE..."

        # burn a line
        # the line after the one that contains the physical drive ID
        # has nothing we want
        read

        # read in the line that will tell us where linux has mounted
        # the drive. usually /dev/s__
        read line

        # grab the basic location i.e. /dev/sdb
        dev_location="$(echo $line | head -c8)"

        # my USB drives have 3 partitions and I have created a permanent location
        # for them in my /mnt drive.
        # this will attempt to mount the partitions. If they are already mounted
        # then mount will display this
        sudo mount -t "$MY_FILE_FORMAT" -o uid="$MY_USER_ID" "$dev_location""1" /mnt/s-one
        sudo mount -t "$MY_FILE_FORMAT" -o uid="$MY_USER_ID" "$dev_location""2" /mnt/s-two
        sudo mount -t "$MY_FILE_FORMAT" -o uid="$MY_USER_ID" "$dev_location""3" /mnt/s-three
    fi

    # takes the current line and looks for the physical ID
    # of the P_DRIVE
    test="$(echo "$line" | grep "$P_ID")"

    # if the ID was found then attempt to mount the drives
    if [[ "$test" != "" ]]; then

        number_of_drives_found=$(( $number_of_drives_found + 1 ))

        echo
        echo "P_DRIVE FOUND!"
        echo "Attempting to mount P_DRIVE..."

        # burn a line
        # the line after the one that contains the physical drive ID
        # has nothing we want
        read

        # read in the line that will tell us where linux has mounted
        # the drive. usually /dev/s__
        read line

        # grab the basic location i.e. /dev/sdb
        dev_location="$(echo $line | head -c8)"

        # my USB drives have 3 partitions and I have created a permanent location
        # for them in my /mnt drive.
        # this will attempt to mount the partitions. If they are already mounted
        # then mount will display this
        sudo mount -t "$MY_FILE_FORMAT" -o uid="$MY_USER_ID" "$dev_location""1" /mnt/p-one
        sudo mount -t "$MY_FILE_FORMAT" -o uid="$MY_USER_ID" "$dev_location""2" /mnt/p-two
        sudomount -t "$MY_FILE_FORMAT" -o uid="$MY_USER_ID" "$dev_location""3" /mnt/p-three
    fi
       
    # if all the drives were found then exit the while loop
    if [ $number_of_drives_found -eq $total_max_drives_to_find ]; then
        break
    fi
done

echo

Posted in BASH, Linux, Programming | Tagged: , , , , , , , , , | Leave a Comment »