Link to home
Start Free TrialLog in
Avatar of dfn48
dfn48

asked on

Using export in shell script

I am new to shell scripting.  I create a program  that read the input from a text file.
Here is my program:
#!/bin/bash 
#alias sas94 is the path to sas executable
export sas94=/sz/sm94/sashome/SASfoundation/9.4/sas

# alias P is the path to the sas program killps.sas

export P=/pt/SOM/

#SAS94 executes killps.sas program and outputs to log filename killps.log

sas94 P/killps.sas -log P/killps.log

#change permission on Ppid.txt
chmod 775 pids=/SA/Ppid.txt

# do while loop  - read in the variable pids and skips over the header  column in  the file.
#Also the program loops  through the file and kill each Ppid value

grep -v "Ppid" pids| while read f1; do
echo "$f1"
kill-9 $f1
done

#this script remove orphans from work directory.The cleanwork function is own by root.
#Sudo and password are needed to execute the script below. The password is passed from db_auth.cfg file without getting prompted.

export cleanwork = 'sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works'
export cleanwork93 = 'sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works'
 
#run cleanwork
cleanwork

#run cleanwork93
cleanwork93

Open in new window



I am getting the following errors:

1. sas94 P/killps.sas is not found
2. P command is not found
3. grep -v "Ppid" pids  
    grep  cannot open pids

4. export: '=' export cleanwork = 'sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works':
      not a valid identifier

5. cleanwork not found
6 .cleanwork93 not found

the content in db_auth.cfg is:
DB_Name=we1234

the contents in Ppid.txt  are:
478889
467974
563492
890762
786655
431290
Avatar of ozo
ozo
Flag of United States of America image

$sas94 $P/killps.sas -log P/killps.log
export cleanwork='sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works'
eval $cleanwork
Pitchers addressed the ......

If you want to define a command, you would use alias, export defines/sets a variable.

Instead of export sas94 use alias sas94

As others pointed out to access data In a variable you need to make sure to use "$P/file name" the quotes are suggested just in the event the file name contains spaces.

Export is unnecessary since your use of the variable is within the script where the variable is defined.

Export is needed if you set/define variables and then run a separate shell script that relies on those variables being defined.
Try the following
#!/bin/bash 
#alias sas94 is the path to sas executable
Alias sas94=/sz/sm94/sashome/SASfoundation/9.4/sas

# alias P is the path to the sas program killps.sas

P='/pt/SOM/'

#SAS94 executes killps.sas program and outputs to log filename killps.log

sas94 "$P/killps.sas" -log "$P/killps.log"

#change permission on Ppid.txt
pids='/SA/Ppid.txt'
chmod 775 "$pids"

# do while loop  - read in the variable pids and skips over the header  column in  the file.
#Also the program loops  through the file and kill each Ppid value

grep -v "Ppid" $pids| while read f1; do
echo "$f1"
kill -9 $f1
done

#this script remove orphans from work directory.The cleanwork function is own by root.
#Sudo and password are needed to execute the script below. The password is passed from db_auth.cfg file without getting prompted.

alias cleanwork = 'sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works'
alias cleanwork93 = 'sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works'
 
#run cleanwork
cleanwork

#run cleanwork93
cleanwork93

Open in new window

Reason for modifications:
1. Always use variables prefixed with $
2. Always use commands with full path name.

Here goes the required modifications:
Replace:
	sas94 P/killps.sas -log P/killps.log
With:
	sas94 $P/killps.sas -log $P/killps.log

Open in new window


Replace:
	chmod 775 pids=/SA/Ppid.txt
With:
	export pids=/SA/Ppid.txt
	/bin/chmod 775 $pids

Open in new window


Replace:
	grep -v "Ppid" pids| while read f1; do
	echo "$f1"
	kill-9 $f1
With:
	/bin/grep -v "Ppid" $pids| while read f1
	do
		if [ `echo -ne "a\ta$f1" | /bin/sed -e "s/\t//g;s/ //g;" |  wc -c` -ne 0 ]
		then
			/bin/echo "kill -9 $f1"
			/bin/echo "Press enter to kill $f1"
			read
			/bin/kill -9 $f1
		fi

Open in new window


Replace:
	export cleanwork = 'sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works'
	export cleanwork93 = 'sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works'
With:
	export cleanwork='/usr/bin/sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works'
	export cleanwork93='/usr/bin/sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork /sn/works'

Open in new window


Replace:
	cleanwork
With:
	$cleanwork

Open in new window


Replace:
	cleanwork93
With:
	$cleanwork93

Open in new window



Also check existense of file names and directory
Example codes:
	if [ -f existingfile.txt ]
	then
		/bin/echo existingfile.txt file is present
	elif [ -L existingfile.txt ]
	then
		/bin/echo existingfile.txt link is present
	elif [ -d existingfile.txt ]
	then
		/bin/echo existingfile.txt directory is present
	else
		/bin/echo existingfile.txt file, dir, and link abscent
	fi

Open in new window

In my comment
Replace:
if [ `echo -ne "a\ta$f1" | /bin/sed -e "s/\t//g;s/ //g;" |  wc -c` -ne 0 ]
With:
if [ `/bin/echo -ne "$f1" | /bin/sed -e "s/\t//g;s/ //g;" |  /usr/bin/wc -c` -ne 0 ]

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Carlos Ijalba
Carlos Ijalba
Flag of Spain 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
Here goes the usage why export is required:
$ /bin/cat  test1.sh
#!/bin/bash
variable="test1"
/bin/echo $variable
/bin/echo "output from . ./test2.sh"
. ./test2.sh
/bin/echo "output from ./test2.sh"
./test2.sh


$ /bin/cat  test2.sh
#!/bin/bash
/bin/echo "variable in test2.sh [ $variable ]"

Open in new window


output:
./test1.sh
test1
output from . ./test2.sh
variable in test2.sh [ test1 ]
output from ./test2.sh
variable in test2.sh [  ]

Open in new window


Hence ./test2.sh require
export variable="value"
Here goes usage of functions and handling exceptions from there:
#!/bin/ksh
unset -f SetUp
SetUp ()
{
        /bin/ls -ld filenotfound >/dev/null 2>&1
        Ret=$?
        return $Ret
}
SetUp
Ret=$?
/bin/echo First time return value $Ret
/bin/echo "Redefining SetUp function"
unset -f SetUp
function SetUp
{
        /bin/ls -ld "$PWD" >/dev/null 2>&1
        /bin/echo "Return value can be till 255 which is 0"
        /bin/echo "Returning 254"
        Ret=254
        return $Ret
}
SetUp

Open in new window

output:
$ ./test1.sh;/bin/echo return value of test1.sh $?
First time return value 2
Redefining SetUp function
Return value can be till 255 which is 0
Returning 254
return value of test1.sh 254

Open in new window

Hence writing script need to handle
SDLC
Software development life cycle
for development/testing/support/calls....
from /usr/bin/head to /usr/bin/tail
Avatar of dfn48
dfn48

ASKER

Thanks you. You are awesome.   one question.    I need to change permission on the pids.txt  before  each line is read  from the file using a do loop.  Is the correct way of coding this for example is as follows?

chmod 755 Ppid=/path/to/pids.txt

grep -v "Ppid" pids| while read f1; do
echo "$f1"
kill-9 $f1
done
Thanks,

I would code it like this:

PPID="/path/to/pids.txt"
chmod 755 $PPID

grep -v "Ppid" pids| while read F1
do
  echo "Killing PID: $F1"
  kill -9 $F1
done

Open in new window


I always put variables and constants in uppercase, to see easily where they are in a terminal monochrome session, and also use indentation to identify loops in logical constructs like while...do, if..then..else, etc

Also there is no need to give cryptic output to the user who is executing the script, just showing numbers on the screen doesn't say anything, but saying killing PID: $VAR, will give a hint of what is doing and if it fails where abouts.

But what Murugesan suggested is also a good practice, and that is to check and report on external commands execution, so after each kill we should catch if it worked OK or not and display it.
Thank you for the comment from Carlos Ijalba.

The following code:
chmod 755 Ppid="/path/to/pids.txt"
grep -v "Ppid" pids| while read f1; do
echo "$f1"
kill-9 $f1
done

Open in new window

can be written throu many ways(way1,way2... numbers not given on priority):
way1:
export PpidFile="/path/to/pids.txt"
if [ -f "$PpidFile" ]
then
	/bin/chmod 755 $PpidFile
	Ret=$?
	if [ 0 -eq $Ret ]
	then
		/bin/grep -v "Ppid" pids| while read RelatedEachPid
		do
			/bin/echo "$RelatedEachPid"
			/bin/kill -9 $RelatedEachPid
			Ret=$?
			if [ 0 -ne $Ret ]
			then
				/bin/echo "kill -9 $RelatedEachPid Fail"
			else
				/bin/echo "kill -9 $RelatedEachPid Pass"
			fi
		done
	else
		/bin/echo "Failed with chmod 755 $PpidFile"
	fi
else
	/bin/echo "$PpidFile file not present"
fi

Open in new window

In my last method way1
Replace:
/bin/grep -v "Ppid" pids| while read RelatedEachPid
With:
/bin/grep -v "Ppid" "$PpidFile"| while read RelatedEachPid
way2 using for loop:
export PpidFile="/path/to/pids.txt"
if [ -f "$PpidFile" ]
then
	/bin/chmod 755 $PpidFile
	Ret=$?
	if [ 0 -eq $Ret ]
	then
		for RelatedEachPid in `/bin/grep -v "Ppid" $PpidFile | /usr/bin/tr "\n" " "`
		do
			/bin/echo "kill -9 $RelatedEachPid"
			/bin/kill -9 $RelatedEachPid
			Ret=$?
			if [ 0 -ne $Ret ]
			then
				/bin/echo "kill -9 $RelatedEachPid Fail"
			else
				/bin/echo "kill -9 $RelatedEachPid Pass"
			fi
		done
	else
		/bin/echo "Failed with chmod 755 $PpidFile"
	fi
else
	/bin/echo "$PpidFile file not present"
fi

Open in new window

Avatar of dfn48

ASKER

I am getting errors when I run the following codes:
1.  error  
~/opt/SM/ps/db_auth.cfg/sasem/sas94m2/sasfoundation/bin/cleanwork    /sn/works path does not exist
function cleanwork 
{
   sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork   /sn/works 
}
cleanwork

Open in new window


2.  error [-f '']'  command not found -f. I am using Aix OS.  Maybe  -f is not a command in AIX.

export PpidFile="/path/to/pids.txt"
if [ -f "$PpidFile" ]
then
	/bin/chmod 755 $PpidFile
	Ret=$?
	if [ 0 -eq $Ret ]
	then
		for RelatedEachPid in `/bin/grep -v "Ppid" $PpidFile | /usr/bin/tr "\n" " "`
		do
			/bin/echo "kill -9 $RelatedEachPid"
			/bin/kill -9 $RelatedEachPid
			Ret=$?
			if [ 0 -ne $Ret ]
			then
				/bin/echo "kill -9 $RelatedEachPid Fail"
			else
				/bin/echo "kill -9 $RelatedEachPid Pass"
			fi

Open in new window

Related to -f option usage in if condition,
Always I used to use ksh shell
which shell you are using inside script
first line of script please ?
at AIX
Replace:
if [ -f "$PpidFile" ]
With:
if [[ -f "$PpidFile" ]]


Also let me know ouput of following
/bin/echo "PpidFile [ $PpidFile ]"
if [[ ":$PpidFile:" != "::" ]]
then
echo PpidFile variable found
else
echo PpidFile variable not found
fi

Open in new window

Also related to
sudo -S apt-get update
I cannot try that
since my laptop(Linux) repair like your script :)
I will update later coming sunday/monday.
Can you try the following:
Replace:
sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork   /sn/works
With:
set -x
sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork   /sn/works
set +x

Also let us know the output of:

for chkDir in `/bin/echo "sudo -S apt-get update <~ $P/db_auth.cfg /szz/sashome/Sasfoundation/bin/cleanwork   /sn/works" |\
/bin/sed "s/.*sudo -S.*update <\~//;"` ~
do
	/bin/echo "chkDir [ $chkDir ]"
	/bin/ls -ld $chkDir
done

Open in new window

Avatar of dfn48

ASKER

I am still getting the same error messages after I made changes to the code.

1.  cleanwork  /saswork  removes  sas orphanded processes in the saswork directory.  Subdirectories under sasem are sas94,  sas92 and sasworks .

 -S apt-get update is not reading in the password from the db_auth.cfg file. This is the errors I am getting.

1.
'/usr/bin/sudo  -S apt-get update <~/opt/SM/ps/db_auth.cfg /sasem/sas92/sashome/sasfoundation/9.2/utilities/bin/cleanwork /sasworks'

line 69   '/usr/bin/sudo  -S apt-get update <~/opt/SM/ps/db_auth.cfg /sasem/sas92/sashome/sasfoundation/9.2/utilities/bin/cleanwork /sasworks: A file or directory in path does not exist

2.
'/usr/bin/sudo  -S apt-get update <~/opt/SM/ps/db_auth.cfg /sasem/sas94/sashome/sasfoundation/9.4/utilities/bin/cleanwork /sasworks'


line 76   '/usr/bin/sudo  -S apt-get update <~/opt/SM/ps/db_auth.cfg /sasem/sas94/sashome/sasfoundation/9.4/utilities/bin/cleanwork /sasworks: A file or directory in path does not exist


Here the code:

function cleanwork 
{
 set -x
    '/usr/bin/sudo  -S apt-get update <~/opt/SM/ps/db_auth.cfg     /sasem/sas92/sashome/sasfoundation/9.2/utilities/bin/cleanwork /sasworks'
set +x
}

function cleanwork94
{
 set -x
    '/usr/bin/sudo  -S apt-get update <~/opt/SM/ps/db_auth.cfg     /sasem/sas94/sashome/sasfoundation/9.4/utilities/bin/cleanwork  /sasworks'
set +x
}

./cleanwork

./cleanwork94

Open in new window

~/ is relative to the user under whose credential the script runs.

Use explicit path when possible.
use cd/chdir to position the script where you want it if necessary.
try to avoid using relative references in commands or directories.
Especially if you set these to run as a cron job.  Cron does not have all the parameters set compared to your login.
If you want, define the PATH, etc atop your script. so that your commands will be found by their name versus with the full paths.
Let us know the output of
/bin/ls -ld ~/opt/SM/ps/db_auth.cfg \
/sasem/sas*/sashome/sasfoundation/9*/utilities/* \
/sasem/sas*/sashome/sasfoundation/9*/utilities/bin/cleanwork \
/sasem/sas*/sashome/sasfoundation/9*/utilities/bin/cleanwork/* \
/sasworks
Avatar of dfn48

ASKER

When I execute the kill pid process script. I am getting the following error message

  -f: command cannot be found. I am using AIX  OS.

export PpidFile="/path/to/pids.txt"
if [[ -f "$PpidFile" ]]
then
      /bin/chmod 755 $PpidFile
      Ret=$?
      if [ 0 -eq $Ret ]
      then
            for RelatedEachPid in `/bin/grep -v "Ppid" $PpidFile | /usr/bin/tr "\n" " "`
            do
                  /bin/echo "kill -9 $RelatedEachPid"
                  /bin/kill -9 $RelatedEachPid
                  Ret=$?
                  if [ 0 -ne $Ret ]
                  then
                        /bin/echo "kill -9 $RelatedEachPid Fail"
                  else
                        /bin/echo "kill -9 $RelatedEachPid Pass"
                  fi
Avatar of dfn48

ASKER

I get an error running the following code:
!#/bin/bash
/bin/ls -ld ~/opt/SM/ps/db_auth.cfg \
/sasem/sas*/sashome/sasfoundation/9*/utilities/* \
/sasem/sas*/sashome/sasfoundation/9*/utilities/bin/cleanwork \
/sasem/sas*/sashome/sasfoundation/9*/utilities/bin/cleanwork/* \
/sasworks

Open in new window


I changed the code and I am still getting error messages.
 
cleanwork is neither a directory nor a file. It is a program that removes orphanes in a sasworks directory.  The program can only be executed by root.

Here is my  code which is not working:
!#/bin/bash

sasadm ALL = NOPASSWD: ALL

 WORK='/saswork'
 cleanwork92='/usr/bin/sudo   /sasem/sas92/sashome/sasfoundation/9.2/utilities/bin/'
   
   echo $cleanwork92

    cd $cleanwork92
   ./cleanwork  /$work


 cleanwork94='/usr/bin/sudo   /sasem/sas94/sashome/sasfoundation/9.4/utilities/bin/' 

   echo $cleanwork94

    cd $cleanwork94
  
     ./cleanwork  /$work

Open in new window

replace:
!#/bin/bash
with:
#!/bin/bash
Replace your code with:
#!/bin/bash
sasadm ALL = NOPASSWD: ALL
WORK='/saswork'
cleanwork92='/sasem/sas92/sashome/sasfoundation/9.2/utilities/bin/'
echo $cleanwork92
cd $cleanwork92
./cleanwork  /$work
cleanwork94='/sasem/sas94/sashome/sasfoundation/9.4/utilities/bin/'
echo $cleanwork94
cd $cleanwork94
./cleanwork  /$work

Open in new window

if running cleanwork  is allowed to execute as root:
Execute the following in above code:
sudo -u root ./cleanwork  /$work

Open in new window

OR
sudo ./cleanwork  /$work

Open in new window

I have seen following variable in your code:
WORK='/saswork'
CAPS WORK here

./cleanwork  /$work
small work here ?
I would like to know the comment on
Accepted Solution
by
1. Administrator of experts-exchange.com
2. Author dfn48
Avatar of dfn48

ASKER

I have tried many different ways and I am still getting prompted for passwork.  I am also getting an error message that says sudo invalid

Here is the prior code :
 
#!/bin/bash
sasadm ALL = NOPASSWD: ALL
WORK='/saswork'
cleanwork92='/sasem/sas92/sashome/sasfoundation/9.2/utilities/bin/'
echo $cleanwork92
cd $cleanwork92
sudo -u root ./cleanwork  /$work
cleanwork94='/sasem/sas94/sashome/sasfoundation/9.4/utilities/bin/'
echo $cleanwork94
cd $cleanwork94
sudo -u root ./cleanwork  /$work

Open in new window



I have given up on the no prompting for password code

What i need mostly now is for my code to work.  I am  getting the following error messages: Path does not exist  and sudo is invalid

cleanwork is not a directory, it is a software program that remove pid objects from sasworks directory.
The hard part is getting cleanwork to execute in a shell script.

Here is my current code:
#!/bin/bash
#cleanwork is not a directory. It is a program that remove pid objects from sasworks  directory. 
# cleanwork is not  in the same path as sasworks directory. 

 WORK='/saswork'
 cleanwork92='/usr/bin/sudo   /sasem/sas92/sashome/sasfoundation/9.2/utilities/bin/ cleanwork /$saswork'
$cleanwork92   


 cleanwork94='/usr/bin/sudo   /sasem/sas94/sashome/sasfoundation/9.4/utilities/bin/ cleanwork /$saswork'

$cleanwork94 

Open in new window

Avatar of dfn48

ASKER

I have tried many different ways and I am still getting prompted for password.  

I have given up on the no prompting for password code

What i need mostly now is for my code to work.  I am  getting the following error messages: Path does not exist  and sudo is invalid

cleanwork is not a directory, It is a software program that remove pid objects from sasworks directory.

The hard part is getting cleanwork to execute in a shell script.

Here is my current code:
#!/bin/bash
#cleanwork is not a directory. It is a program that remove pid objects from sasworks  directory. 
# cleanwork is not  in the same path as sasworks directory. 

 WORK='/saswork'
 cleanwork92='/usr/bin/sudo   /sasem/sas92/sashome/sasfoundation/9.2/utilities/bin/ cleanwork /$saswork'
$cleanwork92   


 cleanwork94='/usr/bin/sudo   /sasem/sas94/sashome/sasfoundation/9.4/utilities/bin/ cleanwork /$saswork'

$cleanwork94 

Open in new window

dfn48,

You really should open new questions for each problem you have, since they are different things, and your original issue has been solved.

Basically sudo prompting for password is another problem, and it is not working for you because you do have to perform a series of steps, mainly: to add the no prompt for password option on /etc/sudoers file, the which is done with the visudo command.

The problem with executing your cleanwork executable is really with sudo config once again or maybe with the PATH variable.

Basically, to write a good script:

1.- first try the commands that you want to execute yourself on the command line and get the parameters, paths and commands right. Run this commands with the user that has native authorization to do so (root, sas, oracle, etc).

2.- secure the commands in point 1 by using sudo, or RBAC, or whatever.

3.- once you have 1 & 2 working OK, then you can just write those commands in a script and try your script.

4.- to debug your script, use:
      set -x
at the beginning of your script, and once you got everything running OK, comment the "set -x" command.