how to get fully qualified directory in bash - bash

This is the structure of my directory:
/rabbitProps, /app and/app/xyz
There is a bash script that i need to edit. In the bash script, there is a variable called BASEDIR and that has the value of "/app/xyz". I need to essentially concatenate the directory of /rabbitProps to a variable called CLASSPATH in the script but not sure how to do that. This is my if statement in the script:
amqDirectory=${BASEDIR}/../rabbitProps/
echo $amqDirectory
echo $BASEDIR
if [ -d "$amqDirectory" ]; then
echo "--SETTING rabbitProps PROPERTIES"
echo "In the if statement for setting rabbitProps"
echo $amqDirectory
CLASSPATH="${CLASSPATH}:${amqDirectory}"
else
echo "--NOT SETTING AMQ PROPERTIES"
echo "In the else if statement for setting amq_properties"
echo $amqDirectory
fi
echo $BASEDIR
echo $CLASSPATH
but it keeps on going to the else block. when i print out the amqDirectory variable, it has the value of /app/xyz/../rabbitProps/ ... which is probably why it's failing the if condition. Can someone correct the expression? I'm not really familiar with bash.

Change your line amqDirectory=${BASEDIR}/../rabbitProps/ to the following
amqDirectory=$(realpath "${BASEDIR}/../rabbitProps/")
Utility realpath gives the resolved path
If the utility is not available, you could do it this way
amqDirectory=$(cd "$BASEDIR/../rabbitProps/"; pwd)
Also, directory is not changed to $BASEDIR/../rabbitProps/ after executing above command as $(..) does the command substitution and it invokes sub-shell for executing commands

Related

Looking for the existence of an ENV Variable

So, I'm guessing this may be a bug, or maybe I've botched something up, I dunno...
I have a script that was always working but I've been tasked to make it work using the new WSL2. I've snipped out the first block of code as it's giving me issues right off the bat. As you'll see below, I'm simply trying to determine if a variable has been set or not. This works in my Linux VM and also in Cygwin, however, it doesn't work in WSL2. Here is the code:
#!/bin/bash
echo $test_var
set -e
if [ ! -d "$test_var" ]; then
echo Please set test_var.
exit
fi
When I run this in any of the working systems I get the output of the variable.
In WSL2 I get the output of the variable followed by Please set test_var. And it stops the script due to the set -e as it's supposed to do thinking the var isn't set.
Any help would be appreciated.
Thanks
If your intention is to check if a directory exists (whose name apparently needs to be set as an environment variable in $test_var), if that directory exists relative to the current directory where the script is executed, you want something like:
#!/bin/bash
echo "$test_var"
set -e
if [ ! -d "$test_var" ]; then
echo "cannot find directory $test_var"
exit
fi
Note that here I have only changed your message, and your problem might possibly be explained by the fact that you do not have such a directory under WSL2.
If, on the other hand, you want to check if some environment variable (whatever it represents) is set, you want the -z option, something like:
#!/bin/bash
echo "$test_var"
set -e
if [ -z "$test_var" ]; then
echo "Please set test_var."
exit
fi
Note the absence of your negation sign (!).

Variable from another file echoed but not recognized in the script

I have a variable in a file called access.txt located at /home/ubuntu/pub/access.txt. The access.txt contents looks like this:
SFTP_VAR="JHGSYDDUIGUIGUIGUIG"
SQL_VAR="GUIIGGJHGBJHGJHGJH"
I have a script file on the same machine that is supposed to read and use this SFTP_VAR. I use the source statement to mention the location of access.txt. Here is the code on my script file.
#!/bin/bash
source /home/ubuntu/pub/access.txt
echo $SFTP_VAR
export SSHPASS=$SFTP_VAR
for f in /home/ubuntu/pub/sfmc/Upstream/Encrypted/* ;
do
echo put "$f"
done | sshpass -e sftp -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-dss USERNAME#FTP_SERVER_IP:/Import
unset SSHPASS
When I run my script, I see the variable in the first echo. This means my script can see the file. But the export command immediately after the first echo does not seem to recognize my variable. This is when I replace the variable with its real value or:
echo 'JHGSYDDUIGUIGUIGUIG'
export SSHPASS='JHGSYDDUIGUIGUIGUIG'
The code works fine. What am I missing here and how can I read those variables in the code?
Edit: During further discussion in the comments it was found to be a problem with the quotes and not with sessions. Changing the double quotes to single quotes in the access.txt file solved it for OP.
I will leave my original answer below.
Your question is very poorly worded. I think I see your problem, but I am not sure.
It seems you might have some misunderstandings of how source and export work and how they affect your session. Lets test this:
First create a file with this content and give the path at line 6 of the script:
VAR1="value of VAR1"
VAR2="value of VAR2"
Then create this script called script.sh:
#!/bin/bash
echo "[The variables with the name VAR1 and VAR2 are undefined in out session]"
echo "VAR1: "$VAR1
echo "VAR2: "$VAR2
echo "[Source brings the variables of the file into our session, with them VAR1 and VAR2]"
source /home/X/access.txt
echo "[VAR1 and VAR2 of our session do now have the values specified in the file]"
echo "VAR1: "$VAR1
echo "VAR2: "$VAR2
echo "[A third undefined variable is used - empty]"
echo "VAR3: "$VAR3
echo "[The third variable gets the value of VAR1 and is exported]"
export VAR3=$VAR1
echo "[The third variale is now filled]"
echo "VAR3: "$VAR3
echo "[We unset the variable]"
unset VAR3
echo "[The variable is no longer set]"
echo "VAR3: "$VAR3
echo "[Set it again]"
export VAR3=$VAR1
echo "[Its back now]"
echo "VAR3: "$VAR3
I think it covers everything you want to do. Now on to testing:
First step:
Just use a normal call on itbash script.sh. Then look at the stdout. Everything should be there as is described by the echos.
Second step:
Now try echo $VAR3 from your shell where you previously called the script. It should not print anything. The variables did not hold their values after the script completed.
Third step:
Now call the script again with export script.sh. Output should look just the way it did in the first step.
Fourth step:
Now try echo $VAR3 again. It will now print the variable.
Why is that?
Bash is based on different sessions. Things you set after you started your session will not carry over to other open sessions and will be lost after you exit the session.
You can start new sessions by simply typing bash. But even this does not solve our problem.
When you call your script you use bash script.sh. This actually also starts a new session and then executes your script inside of this session. Not in the one you called it from.
After finishing it exits out of this session leaving behind the set variables. This is why you cant see them by simple using bash script.sh
In the third step we used source to call the script. This will get the variables into our session and thus we can print the values out.
But this still makes them only temporary as they will go away once we close the session where we sourced the script.
Put things in double quotes. Your example SFTP_VAR="JHGSYDDUIGUIGUIGUIG" should work fine, but try the password "*".
# Incorrect
SFTP_VAR="*"; export SSHPASS=$SFTP_VAR; echo $SSHPASS
# Correct
SFTP_VAR="*"; export SSHPASS="$SFTP_VAR"; echo "$SSHPASS"

Setting path from bash script does not affect globally

I have got this shell script in init.sh
echo "hello";
export ANDROID_HOME=/home/sadaf2605/adt-bundle-linux-x86-20140702/sdk;
export PATH=${PATH}:/home/sadaf2605/adt-bundle-linux-x86-20140702/sdk/tools;
export PATH=${PATH}:/home/sadaf2605/adt-bundle-linux-x86-20140702/sdk/platform-tools
echo "end"
echo $PATH
And had this printed:
sadaf2605#sadaf-pc:~/Estimator-cordova$ ./init.sh
hello
end
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/sadaf2605/adt-bundle-linux-x86-20140702/sdk/tools:/home/sadaf2605/adt-bundle-linux-x86-20140702/sdk/platform-tools
Looks good, I know, but then immediately when I echo $Path I get nothing I did:
sadaf2605#sadaf-pc:~/Estimator-cordova$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
sadaf2605#sadaf-pc:~/Estimator-cordova$
Why did it not work and how can I make it work?
it's because when you execute it you fork a new process for it to run in, it returns to your process when it's done. To see this put an echo $$ in it to show the PID process ID.
you need to run it in your current process to do that use the source command
$source ./your_script

How to prevent direct bash script execution and allow only usage from other script?

I have one script with common functions that is included in other my scripts with:
. ~/bin/fns
Since my ~/bin path is on the PATH, is there a way to prevent users to execute fns from command line (by returning from the script with a message), but to allow other scripts to include this file?
(Bash >= 4)
Just remove the executable bit with chmod -x . ~/bin/fns. It will still work when sourced, but you can't call it (accidentally) by its name anymore.
Some scripts at my workplace use a special shebang
#!/bin/echo Run:.
which returns
Run:. <pathname>
when you use it as a command.
Add the following at the beginning of the script you want to be only allowed to be sourced:
if [ ${0##*/} == ${BASH_SOURCE[0]##*/} ]; then
echo "WARNING"
echo "This script is not meant to be executed directly!"
echo "Use this script only by sourcing it."
echo
exit 1
fi
This will check if the current script and executed shell script file basenames match. If they match, then obviously you are executing it directly so we print a message and exit with status 1.
if (return 0 2>/dev/null) ; then
:
else
echo "Error: script was executed."
exit 1
fi

Bash script exiting prematurely when calling another script inside it

I have a bash script which calls another bash script, like so:
#!/bin/bash
echo "Hi"
./script-two.sh
echo "Hello!"
The problem that I have is that it never makes it to printing "Hello!"
I think this is because ./script-two.sh (Which I did not write) is somehow exiting or changing the shell. I have included this script at the end of this post.
Is there a way I can gurentee that my execution will continue after script-two.sh executes?
I have looked into using the trap command, but I don't fully understand its use properly.
Thanks,
Casey
Here is the contents of what would be script-two.sh
#!/bin/sh
# This file is part of the DITA Open Toolkit project hosted on
# Sourceforge.net. See the accompanying license.txt file for
# applicable licenses.
# (c) Copyright IBM Corp. 2006 All Rights Reserved.
export DITA_HOME=cwd
if [ "${DITA_HOME:+1}" != "1" ]; then
echo "DITA_HOME environment variable is empty or not set";
exit 127;
fi
echo $DITA_HOME
cd "$DITA_HOME"
# Get the absolute path of DITAOT's home directory
DITA_DIR="`pwd`"
echo $DITA_DIR
if [ -f "$DITA_DIR"/tools/ant/bin/ant ] && [ ! -x "$DITA_DIR"/tools/ant/bin/ant ]; then
chmod +x "$DITA_DIR"/tools/ant/bin/ant
fi
export ANT_OPTS="-Xmx512m $ANT_OPTS"
export ANT_OPTS="$ANT_OPTS -Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl"
export ANT_HOME="$DITA_DIR"/tools/ant
export PATH="$DITA_DIR"/tools/ant/bin:"$PATH"
NEW_CLASSPATH="$DITA_DIR/lib:$DITA_DIR/lib/dost.jar:$DITA_DIR/lib/commons-codec-1.4.jar:$DITA_DIR/lib/resolver.jar:$DITA_DIR/lib/icu4j.jar"
NEW_CLASSPATH="$DITA_DIR/lib/saxon/saxon9.jar:$DITA_DIR/lib/saxon/saxon9-dom.jar:$NEW_CLASSPATH"
NEW_CLASSPATH="$DITA_DIR/lib/saxon/saxon9-dom4j.jar:$DITA_DIR/lib/saxon/saxon9-jdom.jar:$NEW_CLASSPATH"
NEW_CLASSPATH="$DITA_DIR/lib/saxon/saxon9-s9api.jar:$DITA_DIR/lib/saxon/saxon9-sql.jar:$NEW_CLASSPATH"
NEW_CLASSPATH="$DITA_DIR/lib/saxon/saxon9-xom.jar:$DITA_DIR/lib/saxon/saxon9-xpath.jar:$DITA_DIR/lib/saxon/saxon9-xqj.jar:$NEW_CLASSPATH"
if test -n "$CLASSPATH"
then
export CLASSPATH="$NEW_CLASSPATH":"$CLASSPATH"
else
export CLASSPATH="$NEW_CLASSPATH"
fi
"$SHELL"
It looks like script-two.sh is setting up an ant build environment.
I think the author intended that it sets up the build environment, then you type your build commands in manually, then type exit to leave the build environment.
I say this because the bottom line of script-two.sh is:
"$SHELL"
which starts a new shell.
Try running your script, then type exit. I think you will see it print Hello! after you type exit.
I'm guessing you're trying to do something like:
#!/bin/bash
echo "Hi"
./script-two.sh
ant <some args>
To do that, what you really want to do is source it, by changing:
./script-two.sh
to
. script-two.sh
e.g.
#!/bin/bash
echo "Hi"
. script-two.sh
ant <some args>
But, you will need to edit script-two.sh and change:
"$SHELL"
to:
case $0 in *script-two.sh)
# executed, start a new shell with the new environment
"$SHELL"
;;
*)
# sourced, don't start a new shell
;;
esac
so that it only starts a shell if the script is being run like ./script-two.sh, but not if it is being sourced like . script-two.sh.
Or if you absolutely can't change script-two.sh, then you could do:
#!/bin/bash
echo "Hi"
. script-two.sh </dev/null
ant <some args>
which will trick "$SHELL" into exiting because it has no input.
Also
export DITA_HOME=cwd
doesn't seem right to me.
It should probably be
export DITA_HOME=$(pwd)
or
export DITA_HOME=`pwd`
(both are equivalent)
I had a similar problem today, up on digging I finally found the answer.
The script I was calling (from within my script) actually had an exit 0 in the end. Removing that fixed my issues.
Just leaving this here as someone may find it useful.
Well for starters, you can execute your bash script with the -x switch to see where it is failing:
bash -x script-one.sh
Secondly, if you call the second script like this:
#!/bin/bash
echo "Hi"
var=$(bash script-two.sh)
echo "Hello!"
It will continue, as long as script-two.sh exits cleanly. Again, you can run the -x script against that script find any problems.
And as Mikel mentioned, always make sure to have exit at the bottom of your scripts.

Resources