Link to home
Start Free TrialLog in
Avatar of labradorchik
labradorchikFlag for United States of America

asked on

How to test script environmental logicals/variables in Unix/bash?

How to test environmental logicals/variables in Unix/bash script with another Unix/bash script?  

I have below script that creates environmental logicals/variables, - those logicals/variables will be used in some other future scripts as well for efficiency reason. The purpose is to use only logicals/variables and not full directories in future scripts.  What would be another script that would test each of theses logicals/variables? Please provide an example if you can.

#!/bin/bash
export DATADIR1=/root/alldirs/2018/data1
export DATADIR2=/root/alldirs/2018/data2
export DATADIR3=/root/alldirs/2018/data3
echo "This script just stopped running"

Open in new window


Any suggestions would be appreciated!
Thank you!
Avatar of Sujith
Sujith
Flag of United Kingdom of Great Britain and Northern Ireland image

You need to source the script that sets the environment variables in the second script

Something like the below. where test.sh is the script you have attached in the question -

source test.sh

echo $DATADIR1;
echo $DATADIR2;

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of MURUGESAN N
MURUGESAN N
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You'll see above that Sujith has used the syntax:
    source <scriptname>
while Murugesan has used this more concise alternative, which is basically the same:
    . ./<scriptname>

Some comments on "sourcing" scripts, and the solutions above.
Sujith's solution has ";" at the end of the lines, e.g.
    echo $DATADIR1;
There is no need for the ";" in this case.  It would be needed if he had more than one command on a line.
Murugesan's solution has:
    export DATADIR1=/root/alldirs/2018/data1
as does your script.  From my tests, there is no need to export these variables.  Try it youself to confirm.
There's also no need to start the script which is being "sourced" with a shebang line, so you can remove the "!#/bin/bash".
And the script being sourced doesn't even need to be executable.
Avatar of labradorchik

ASKER

Thank you everyone for helping and providing your solutions and suggestions! The found the most useful solution from Murugesan, where each directory can be tested to make sure they all exist. Thank you again everyone!!
Hi labradorchik,

You can award points as you want to, but are you aware that you can split points so that it's not only the best solution which gets credit?

More comments regarding Murugesan's solution:

      if [[ -x ./SETENV.sh ]]      # The -x includes a check for executability, but SETENV.sh doesn't need to be executable
      then
            . ./SETENV.sh     # Can be more simply written as: ". SETENV.sh", I believe
            if [[ 0 -eq $SETENVERR ]]    # The normal way to write this is: if [[ $SETENVERR -eq 0 ]]

And this code:
                  if [[ ! -d "$DATADIR1" ]]
                  then
                        echo "DATADIR1 $DATADIR1 No such directory"
                        $ERROR
                  elif [[ ! -d "$DATADIR2" ]]
                  then
                        echo "DATADIR2 $DATADIR2 No such directory"
                        $ERROR
                  elif [[ ! -d "$DATADIR3" ]]
                  then
                        echo "DATADIR3 $DATADIR3 No such directory"
                        $ERROR
                  else
will report only the first non-existent directory, but that's probably OK for most applications.

And the "quotes" can be removed from this kind of bash statement:
      if [[ ! -d "$DATADIR1" ]]
#!/bin/bash
# >> TEL2
# >> You can award points as you want to
# Agreed :)
# Sample code1...
if [[ ! -f SETENV.sh ]]
then
      echo "\$PWD $PWD"
      echo "/bin/ls -l SETENV.sh"
      /bin/ls -l SETENV.sh
else
      # The -x includes a check for executability, but SETENV.sh doesn't need to be executable
      # Agreed :)
      # @labradorchik can change ./ to required directory(Example:$PWD) or remove ./ based on requirement
      SETENVPATH=$(/bin/dirname SETENV.sh)
      if [[ "." = "$SETENVPATH" ]]
      then
            SETENVPATH="$PWD"
      fi
      echo $SETENVPATH
      if [[ -f "$SETENVPATH/SETENV.sh" ]]
      then
            . "$SETENVPATH/SETENV.sh"
            # I was from C++ C(Linux/UNIX/AIX/SunOS/HP-UX/CYGWIN_NT)
            # To remove future exceptions (due to new joinees) C C++ and Makefile(using shell script at all OS)
            # used to prefer this format in C++, C Makefile and shell scripting.
            # Hence followed this way
            if [[ 0 -eq $SETENVERR ]]
            then
                  if [[ ! -d "$DATADIR1" ]]
                  then
                        echo "DATADIR1 $DATADIR1 No such directory"
                        $ERROR
                  elif [[ ! -d "$DATADIR2" ]]
                  then
                        echo "DATADIR2 $DATADIR2 No such directory"
                        $ERROR
                  elif [[ ! -d "$DATADIR3" ]]
                  then
                        echo "DATADIR3 $DATADIR3 No such directory"
                        $ERROR
                  else
                        echo "Sample test1 $0"
                        echo "$DATADIR1 directory is present PASS"
                        echo "$DATADIR2 directory is present PASS"
                        echo "$DATADIR3 directory is present PASS"
                  fi
            fi
      else
            echo "\$PWD $PWD"
            echo /bin/ls -l "$SETENVPATH/SETENV.sh"
            /bin/ls -l "$SETENVPATH/SETENV.sh"
      fi
fi
# >> will report only the first non-existent directory.
# Updated Sample code2
# Thank you TEL2 for all comments.
if [[ ! -f SETENV.sh ]]
then
      echo "\$PWD $PWD"
      echo "/bin/ls -l SETENV.sh"
      /bin/ls -l SETENV.sh
else
      if [[ -f "$SETENVPATH/SETENV.sh" ]]
      then
            . "$SETENVPATH/SETENV.sh"
            #OR
            #source "$SETENVPATH/SETENV.sh"
            if [[ 0 -eq $SETENVERR ]]
            then
                  if [[ -d "$DATADIR1" && -d "$DATADIR2" && -d "$DATADIR3" ]]
                  then
                        echo "Sample test2 $0"
                        echo "$DATADIR1 directory is present PASS"
                        echo "$DATADIR2 directory is present PASS"
                        echo "$DATADIR3 directory is present PASS"
                  else
                        if [[ ! -d "$DATADIR1" ]]
                        then
                              echo "DATADIR1 $DATADIR1 No such directory"
                              $ERROR
                        fi
                        if [[ ! -d "$DATADIR2" ]]
                        then
                              echo "DATADIR2 $DATADIR2 No such directory"
                              $ERROR
                        fi
                        if [[ ! -d "$DATADIR3" ]]
                        then
                              echo "DATADIR3 $DATADIR3 No such directory"
                              $ERROR
                        fi
                  fi
            fi
      else
            echo "\$PWD $PWD"
            echo /bin/ls -l "$SETENVPATH/SETENV.sh"
            /bin/ls -l "$SETENVPATH/SETENV.sh"
      fi
fi

$ ./29099107.sh
$PWD /home/murugesandins
/bin/ls -l SETENV.sh
/bin/ls: cannot access 'SETENV.sh': No such file or directory
$PWD /home/murugesandins
/bin/ls -l SETENV.sh
/bin/ls: cannot access 'SETENV.sh': No such file or directory

Open in new window

$ ./29099107.sh
/home/murugesandins
Sample test1 ./29099107.sh
/root/alldirs/2018/data1 directory is present PASS
/root/alldirs/2018/data2 directory is present PASS
/root/alldirs/2018/data3 directory is present PASS
Sample test2 ./29099107.sh
/root/alldirs/2018/data1 directory is present PASS
/root/alldirs/2018/data2 directory is present PASS
/root/alldirs/2018/data3 directory is present PASS

Open in new window

Thanks for the improvements, Murugesan.

           # I was from C++ C(Linux/UNIX/AIX/SunOS/HP-UX/CYGWIN_NT)
            # To remove future exceptions (due to new joinees) C C++ and Makefile(using shell script at all OS)
            # used to prefer this format in C++, C Makefile and shell scripting.
            # Hence followed this way
            if [[ 0 -eq $SETENVERR ]]

Q1. Can you prove that issue with C++/C?
Q2. Why are you applying this strange requirement of some old C++/C version to bash?

Q3. Why do you use "quotes" in tests like this?:
   if [[ ! -d "$DATADIR1" ]]
>> Can you prove that issue with C++/C?
#include <stdio.h>
int main()
{
        int incidentId = 0;
        if ( incidentId = 29099107 )
        {
                printf( "Sample exception %d\n", incidentId);
        }
        else
        {
                printf( "Handled exception %d\n", incidentId);
        }
        return 0;
}
// $ ./a.out
// Sample exception 29099107

Open in new window

I agree based on warnings (-Wall), we can remove such exception. However when the source code count increases(thousands of source files... from open source), that becomes difficult.
$ /bin/sed "s/\(incidentId \)\(=\)\( 29099107\)/\3\2\1/;"  29099107.c
$ /usr/bin/gcc -g -Wall 29099107.c -o ./a.out
29099107.c: In function ‘main’:
29099107.c:5:16: error: lvalue required as left operand of assignment
  if ( 29099107 = incidentId )

Open in new window

>> Assume that a developer writing the script using variable operator value, same used to be followed using C C++. Hence followed the same.

>> Why do you use "quotes" in tests like this?:
I cannot remember the error faced during 2005 to 2006 => few errors happened using common Makefile at all platforms.

echo "Thank you and welcome :) "| /usr/bin/wc
Hi Murugesan,

Q4. Regarding the C/C++ code you've provided, I don't know much C, but why are you using the "=" (assignment operator) instead of the "==" (equivalence operator), in this line?:
       if ( incidentId = 29099107 )
I expect that would always return a true result because the assignment succeeds.

Q5. Does this solve the problem?:
       if ( incidentId == 29099107 )

>> Why do you use "quotes" in tests like this?:
> I cannot remember the error faced during 2005 to 2006 => few errors happened using common Makefile at all platforms.

I'm not talking about Makefiles.  I'm taking about the "quotes" in bash tests like this:
          if [[ ! -d "$DATADIR1" ]]
Please answer question Q3 again, plus Q4 & Q5.

Thanks.
Q3)
I cannot remember the code (script @ all OS) error happened because of parsing EDI files => it was present in given script using more conditional operators => or, and xor /bin/sed
Release code (all binaries including setup.sh) need to meet all requirements mentioned in design documents.
>> It was something like standardized version of UNIX version 5 => present in Design of UNIX operating system from Maurice J Bach
Q4)
>> I expect that would always return a true result because the assignment succeeds.
During 2005/2006 given source code was having that issue due to SIGSEGV
Using -g recompilation, reproducing the error, ulimit -c unlimited and gdb found that error.
Hence proceeded using "value operator variable"
After resolving that, we have removed -g, ulimit and re compiled.
Q5)
>> if ( incidentId == 29099107 )
developer may miss = operator here
Hi Murugesan,

Q5)
>> if ( incidentId == 29099107 )
> "developer may miss = operator here"

That does not answer my question.  Please read my question Q5 from post #42563248, and then answer it.

Thanks.
Q5. Does this solve the problem?:
       if ( incidentId == 29099107 )
>> Why do you use "quotes" in tests like this?:

when DATADIR1 may have spaces (writing the code to execute the script at all OS)
Sample:
C:\PROGRA~2\INTERN~1 => /cygdrive/c/PROGRA~2/INTERN~1 OR /cygdrive/c/Program Files (x86)/Internet Explorer
Faced that issue when directory was having special characters => multi language support at all OS
written generalized script across platforms.
This question of mine:
                 Q5. Does this solve the problem?:
                      if ( incidentId == 29099107 )

has nothing to do with this other question of mine:
                 >> Why do you use "quotes" in tests like this?:
The "quotes" question was Q3.

So please answer this question in regard to the C code sample you provided at the top of post #42563241:
                 Q5. Does this solve the problem?:
                      if ( incidentId == 29099107 )
if ( incidentId == 29099107 ) => Yes, it solves the problem.

C C++ programmer used to write "if ( incidentId = 29099107 )" instead of "if ( incidentId == 29099107 )"
missing = operator.
This used to cause issues over most of the data types.
Hence informed the team to have value on right and variable on left.
Informed the developers to proceed the same way even when using script => Since using that most of the times (script or Makefile or source code) => makes (C CPP) developer not to write "variable = value" format.
Hence proposed value = variable inside script too.
I agree variable = value work using script. However making them to write => will prevent future (C CPP ) developer's exceptions.
There is no need to bring those strange C/C++ habits into bash, especially in a forum where:
a) You haven't documented/explained the reason for the odd syntax in every solution that you provide it.
b) Many of the readers will  quite likely never program in C/C++.
ok, got it. Here after I won't merge script to C/C++ programming oriented.
Sure, I will follow the same.
>> Many of the readers
I understood.
Thank you tel2.