Showing posts with label bash. Show all posts
Showing posts with label bash. Show all posts

Sunday, December 11, 2016

Oracle Linux - transform CSV into JSON with bash

Like it or not, a large number of outputs created by systems is still in CSV, comma separated value, file format. The amount of information that is created, and needs processing, that is represented in CSV format is large. And it is good to understand how you could script against CSV files in your Oracle Linux bash scripts. to use the information or to transform this into other formats. As an example we use the below which is a section of a output file generated by an application that logs the use of doors within a building.

[root@localhost tmp]# cat example.csv
100231,AUTHORIZED,11-DEC-2016,13:12:15,IN,USED,F2D001
100231,AUTHORIZED,11-DEC-2016.13:14:01,IN,USED,F2D023
100231,AUTHORIZED,11-DEC-2016,13:15:23,IN,TIMEOUT,F2D024
100231,AUTHORIZED,11-DEC-2016,13:15:59,IN,USED,F2D024
100562,AUTHORIZED,11-DEC-2016,13:16:01,IN,USED,F1D001
100562,AUTHORIZED,11-DEC-2016,13:16:56,IN,USED,F1D003
100562,AUTHORIZED,11-DEC-2016,13:20:12,OUT,USED,F1D003
100562,AUTHORIZED,11-DEC-2016,13:20:58,IN,USED,F1D004
100231,AUTHORIZED,11-DEC-2016,13:20:59,OUT,USED,F2D024
[root@localhost tmp]#

As you can see from the above data we have some information in a per-line format using a CSV format to seperate the data. In this example the fields have the following meaning:

  • The ID of the access card used
  • The status of the authorization request by the card for a certain door
  • The date the authorization request was made
  • The time the authorization request was made
  • The direction of the revolving door the request was made for
  • The usage status, this can be USED or can be TIMEOUT in case the door was not used
  • The ID for the specific revolving door

The amount of things you might want to do from a data mining or security point of view are endless, however, having a CSV file on the file system of your Oracle Linux server is not making it useful directly. You will have to do something with it. To show you how you can use bash scripting to understand the CSV file itself is shown in the below example script;

#!/bin/bash
INPUT=/tmp/example.csv
OLDIFS=$IFS
IFS=,
[ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 99; }
while read cardid checkstatus checkdate checktime doordirection doorstatus doorid
do
        echo "card used : $cardid"
        echo "check outcome : $checkstatus"
        echo "date : $checkdate"
        echo "time : $checktime"
        echo "direction : $doordirection"
        echo "usage : $doorstatus"
        echo "door used : $doorid"
        echo "----------------------"
done < $INPUT
IFS=$OLDIFS

As you can see in the above example we use the IFS variable to read and separate the values in the CSV file and place them in their own respective variables. The $IFS variable is a special shell variable and stands for Internal Field Separator. The Internal Field Separator (IFS)  is used for word splitting after expansion and to split lines into words with the read builtin command. Whenever trying to split lines into words you will have to look into the $IFS variable and how to use this.

The above example is quite simple and just prints the CSV file in a different way to the screen. More interesting is how you could transform a CSV file into something else, for example a JSON file. In the below example we will transform the CSV file into a correctly formatted JSON file.

#!/bin/bash
# NAME:
#   CSV2JSON.sh
#
# DESC:
#  Example script on how to convert a .CSV file to a .JSON file. The
#  code has been tested on Oracle Linux, expected to run on other
#  Linux distributions as well.
#
# LOG:
# VERSION---DATE--------NAME-------------COMMENT
# 0.1       11DEC2016   Johan Louwers    Initial upload to github.com
#
# LICENSE:
# Copyright (C) 2016  Johan Louwers
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this code; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# *
# */

 inputFile=/tmp/example.csv
 OLDIFS=$IFS


 IFS=,
  [ ! -f $inputFile ] && { echo "$inputFile file not found"; exit 99; }

# writing the "header" section of the JSON file to ensure we have a
# good start and the JSON file will be able to work with multiple
# lines from the CSV file in a JSON array.
 echo "
  {
   \"checklog\":
   ["

# ensuring we have the number of lines from the input file as we
# have to ensure that the last part of the array is closed in a
# manner that no more information will follow. (not closing the
# the section with "}," however closing with "}" instead to
# prevent incorrect JSON formats. We will use a if check in the
# loop later to ensure this is written correctly.
 csvLength=`cat $inputFile | wc -l`
 csvDepth=1

 while read cardid checkstatus checkdate checktime doordirection doorstatus doorid
  do
     echo -e "   {
      \"CARDCHECK\" :
       {
        \"CARDID\" : \"$cardid\",
        \"CHECKSTATUS\" : \"$checkstatus\",
        \"CHECKDATE\" : \"$checkdate\",
        \"CHECKTIME\" : \"$checktime\",
        \"DIRECTION\" : \"$doordirection\",
        \"DOORSTATUS\" : \"$doorstatus\",
        \"DOORID\" : \"$doorid\"
       }"
     if [ "$csvDepth" -lt "$csvLength" ];
      then
        echo -e "     },"
      else
        echo -e "     }"
     fi
   csvDepth=$(($csvDepth+1))
  done < $inputFile

# writing the "footer" section of the JSON file to ensure we do
# close the JSON file properly and in accordance to the required
# JSON formating.
 echo "   ]
  }"

 IFS=$OLDIFS

As you can see, and test, you will now have a valid JSON output format. As JSON is much more the standard at this moment than CSV you can more easily use this JSON format in the next step of the process. You could for example use this to send it to a REST API endpoint for storing in a database, you can use it in a direct manner to upload it to Elasticsearch, or......

However, as stated, the entire way of working is using the $IFS variable available to you as a integrated part of the Linux shell. The above scv2json.sh code is uploaded to github and in case of any changes they will be made only to github.com, feel free to fork it and use it for your own projects. 

Friday, October 21, 2016

Oracle Linux - Checking installed package

In some cases you want to verify if a package is installed on your Oracle Linux instance within a bash script. You query what is installed by using the "list installed" option for the yum command. However, this is giving you a more human readable result and not something that works easy in a the flow of a script. In essence you would like to have a boolean value returned to tell you if a package is installed or not on your Oracle Linux instance.

The below code example is a bash script that will exactly do so. Within the example you see the packageInstalled function which takes a variable for the package name you are looking for. The result will be true or false.

#!/bin/bash

function packageInstalled () {
     numberOfPackages=`yum list installed | grep $1 | wc -l`
     if [ "$numberOfPackages" -gt "0" ];
       then
           echo "true"
     else
         echo "false"
     fi
}

packageInstalled wget

In the example we are checking the installation of the wget package. You can change wget for whatever you need to be sure is installed. Using this building block function can help you to write a more complex script for installing packages when needed. 

Thursday, September 10, 2015

Exadata check IB cables

One of the things that helps make the Exadata perform at the speed it is performing is the fact that the connections between the compute nodes and the storage nodes is based upon Infiniband . In some cases also other, external components, are connected to the Exadata by making use of Infiniband . Infiniband is an intergrated and vital part of Exadata. The below presentation gives a quick introduction into the Infiniband cabling of a full rack Exadata and how you can connect other Oracle Engineered systems to a Exadata Infiniband  fabric.



In normal situations all cables should be present in an Exadata. However, in some cases due to some reason a cable might have been unplugged. As datacenters are often not near the location where engineers are it can be handy to have the ability to check the state of the cables from the commandline without the need to be physically present in the datacenter. The below bash script enables you to check the state of the cables on both the compute as well as the storage servers.

for ib_cable in `ls /sys/class/net | grep ^ib`; do 
  printf "$ib_cable: "; cat /sys/class/net/$ib_cable/carrier; 
done 


The output will tell you if the cable is present per Infiniband interface. A 1 indicates that a cable is found a 0 indicates that no cable is found.

Tuesday, September 18, 2012

Linux print file reversed

Within Linux you have several commands that will read a file and put the output from this file to your screen. Or you can pipe it into an other file if that is what you need. however from time to time you might want to read the file in reversed order. For example if you have an application that is writing information to a file and you have to put this file in reversed order into a input file for another program or to be loaded into a database.

as with most things in Linux there are several ways to dot his. you could read the number of lines by using wc -l and use this number in loop of a bash program to print the file line by line in reversed order.

however, as stated, there are more ways to do this. This most easy way to read a file in reversed order in Linux is making use of the tac command. The tac command will do exactly as described above without any line of coding or any other smart trick. It just reads a file and print the content in reversed order to your screen (or pipe it into another file).

NAME
       tac - concatenate and print files in reverse

SYNOPSIS
       tac [OPTION]... [FILE]...

DESCRIPTION
       Write each FILE to standard output, last line first.  With no FILE, or when FILE is -, read standard input.

       Mandatory arguments to long options are mandatory for short options too.

       -b, --before
              attach the separator before instead of after

       -r, --regex
              interpret the separator as a regular expression

       -s, --separator=STRING
              use STRING as the separator instead of newline

       --help display this help and exit

       --version
              output version information and exit

Friday, April 16, 2010

emctl ulimit: 25: bad number

I have recently installed a Oracle 11G R2 database on my Ubuntu laptop. All is working fine however one little issue is still bugging me. Whenever I start the dbconsole with emctl it is giving me a "ulimit: 25: bad number" warning. Even do all is starting up fine the issue is somehow bugging me. I have done some research and found that the rootcause thanks to some people at the oracle forums page.

The issue can be found in the file $ORACLE_HOME/bin/commonenv which is been called when you use emctl.

"If you type this line into bash, it works just fine, but emctl begins with the line #!/bin/sh, which on Ubuntu systems is symbolically linked to /bin/dash. Now, ulimit is a built-in shell command, not an executable file, and bash and dash seem to have a different syntax. If you type "dash" at a shell prompt to start a new dash shell, and type that particular ulimit command, it will complain about a bad number. (I'm not sure what the "25" represents, that number seems to be related to the number of lines in the shell script in which the command is found.) Be sure to type "exit" when finishing this test to return to bash or whatever your preferred shell is."

What you can do to solve the issue is to change the first line of the emctl script itself from:
#!/bin/sh

into:
#!/bin/bash

this way you will call the bash shell explicitly and the bash version of ulimit is called with the correct syntax. Even do it is not a big issue and you can ignore the error message I just want to have a tidy system which is not bugging me with error messages. As Ubuntu is not a certified system (still) you can encounter things like this and you just have to find a way around it.