Bash script variables not set in CentOS [duplicate] - linux

In bash, if I run
(foo=14)
And then try to reference that variable later on in my bash script:
echo "${foo}"
I don't get anything. How can I make bash store this variable the way I need it to?
Specifically, I am using this in an if statement and checking the exit code, something kind of like:
if (bar="$(foo=14;echo "${foo}"|tr '1' 'a' 2>&1)")
then
echo "Setting "'$bar'" was a success. It is ${bar}"
else
echo "Setting "'$bar'" failed with a nonzero exit code."
fi

Commands enclosed in parenthesis e.g. () are executed in a sub-shell. Any assignment in a sub-shell will not exist outside that sub-shell.
foo=14
bar=$(echo $foo | tr '1' 'a' )
if [[ $? -eq 0 ]]
then
echo "Setting "'$bar'" was a success. It is ${bar}"
else
echo "Setting "'$bar'" failed with a nonzero exit code."
fi

Related

Linux Bash Script String Equality Problem

I tried to run bash script which is like that :
#!/bin/bash
export LD_LIBRARY_PATH=X ## censored
export PATH=$PATH:$LD_LIBRARY_PATH
CONNECTION='X' ## censored
echo $CONNECTION
RETVAL=`sqlplus -silent $CONNECTION <<EOF
SET PAGESIZE 50 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
SELECT 'Alive' FROM dual;
EXIT;
EOF`
echo $RETVAL
if [ "$RETVAL" = "Alive" ];
then
echo 'Database is running.'
exit 1
else
echo 'Database is NOT running.'
fi
exit
When I run this sh result is like that :
sh checkdbstatus.sh
X
Alive
Database is NOT Running.
Why result is not Database is running ?
$RETVAL and Alive are equal ? And I am sure db is running.
Thank you
I expect to see result is Database is running.
I mean, i had read string testing should be done like this (at least with Busybox sh):
if [[ "$RETVAL" == "Alive" ]];
I looked trough some of my own scripts, and since 3 Years i use double brackets "[[" and double equalsigns "=="
I'll also remember i had a problem with invisible char (was some ansi-escape code) in output of an command. I found that by piping the command output to a textfile..
The sqlplus command probably adds an invisible newline character to $RETVAL.
Try this:
if [[ "$RETVAL" =~ ^Alive ]];

How to get the output of if condition on terminal

I have this example and i want to get on screen both condition and good
Code:
if [ `echo condition` ]; then echo good; fi
The output that i want to get:
condition
good
The output that i got:
good
As the command echo condition will be replaced with another command. The if statement must check the return code of the condition command.
Simply store it in a variable:
cond=$(echo condition)
if [ "$cond" ] ; then
echo "$cond"
echo good
fi
Do not use backticks anymore nowadays.
Store the output of your sub shell in a variable:
if condition=$(echo condition); then
echo "$condition"
echo good
fi
If you want to return the exit value of the sub shell, you have to write a function:
get-condition-result()
{
local condition
local result
if condition=$(echo condition); then
result=$?
echo "$condition"
echo good
else
result=$?
fi
return "$result"
}
Solution found here: https://stackoverflow.com/a/13343457/12953642
You can run your command without any additional syntax. For example, the following checks the exit code of grep to determine whether the regular expression matches or not:
if echo condition
then
echo "good"
fi
if echo "condition" && curl
then
echo "good"
else
echo "error in command"
fi
Output:
condition
good
condition
curl: try 'curl --help' or 'curl --manual' for more information
error in command

Terminal closes when I source my script (run with dot at the start)

Here is my code:
#!/bin/bash
if [[ $1 = "" ]]; then
exit 0
fi
array=($(cat $1))
let b=${#array[#]}-1
count=0
for i in {1..7}; do
for j in {30..37}; do
for n in {40..47}; do
if [[ $count -gt $b ]]; then
printf '\n'
printf '\e[0m'
exit 1
fi
printf '\e[%s;%s;%sm%-5s' "$i" "$j" "$n" "${array[$count]}"
printf '\e[0m'
let count=$count+1
done
printf '\n'
done
done
#printf '\n'
printf '\e[0m'
exit 0
The problem is that when I start it like this
. color.sh arg
or without argument, it just closes. I know that the reason for that is exit. Is there any way correct my code so I could start a script with dot at start and terminal wouldn't close after execution? I don't want to start it like this: ./script
Replace all exit with return.
return inside a sourced script will even work with exit codes:
$ . <(echo "echo before; return 0; echo after")
before
$ echo $?
0
$ . <(echo "echo before; return 7; echo after")
before
$ echo $?
7
When you use the dot to run a script you are "sourcing" it, which means the interpreter reads and executes all the commands in that script in the context of the current environment without spawning a subshell, as if you had typed each yourself.
That's why if you source it you can set variables in a script that will remain after it has run, whereas running it in a subshell would encapsulate them, and they would go away when the script ends.
Accordingly, if you source a script that hits an exit, it causes the calling environment to exit. Use return as Socowi suggested.

How to display argument in shell script

I have a shell script called displayArg.sh This is how I intend to run it-
./displayArg hello
and the output is entered arg is hello
The following is the script-
if [ $1 == "" ]; then
default="Default"
echo "no value is given. Output is $default"
else
value=$?
echo "entered arg is $value" #I know I am wrong in these 2 lines, but not sure how to fix it
fi
Kindly bear with me. I'm new to Shell scripting
You want:
value="$1"
($? is the status of the last command, which is 1 because the test command is what was executed last.)
Or you can simplify to:
if [ "$1" == "" ]
then
echo "no value is given. Output is Default"
else
echo "entered arg is $1"
fi
Note the quotes around "$1" in the test. If the string is empty, you get a syntax error. Your alternative with bash is to use a [[ $1 == "" ]] test.

How to enable or disable multiple "echo statements" in bash ecript

I have bash script where i have echo before every command showing what is happening.
But i need to disbale echo when setting as cron job and then enable again if do some testing.
i find it very hard to go to each line and then add/remove comment
is there anything which i can include at top something like
enable echo or disable echo
so that i don't have to waste time
The absolute easiest would be to insert the following line after the hashbang line:
echo() { :; }
When you want to re-enable, either delete the line or comment it out:
#echo() { :; }
If you're not using echo but printf, same strategy, i.e.:
printf() { :; }
If you absolutely need to actually echo/printf something, prepend the builtin statement, e.g.:
builtin echo "This 'echo' will not be suppressed."
This means that you can do a conditional output, e.g.:
echo () {
[[ "$SOME_KIND_OF_FLAG" ]] && builtin echo $#
}
Set the SOME_KIND_OF_FLAG variable to something non-null, and the overridden echo function will behave like normal echo.
EDIT: another alternative would be to use echo for instrumenting (debugging), and printf for the outputs (e.g., for piping purposes). That way, no need for any FLAG. Just disable/enable the echo() { :; } line according to whether you want to instrument or not, respectively.
Enable/Disable via CLI Parameter
Put these lines right after the hashbang line:
if [[ debug == "$1" ]]; then
INSTRUMENTING=yes # any non-null will do
shift
fi
echo () {
[[ "$INSTRUMENTING" ]] && builtin echo $#
}
Now, invoking the script like this: script.sh debug will turn on instrumenting. And because there's the shift command, you can still feed parameters. E.g.:
Without instrumenting: script.sh param1 param2
With instrumenting: script.sh debug param1 param2
The above can be simplified to:
if [[ debug != "$1" ]]; then
echo () { :; }
shift
fi
if you need the instrumenting flag (e.g. to record the output of a command to a temp file only if debugging), use an else-block:
if [[ debug != "$1" ]]; then
echo () { :; }
shift
else
INSTRUMENTING=yes
fi
REMEMBER: in non-debug mode, all echo commands are disabled; you have to either use builtin echo or printf. I recommend the latter.
Several things:
Don't use echo at all
Instead use set -xv to set debug mode which will echo each and every command. You can set PS4 to the desired prompt: for example PS4='$LINENO: ' will print out the line number on each line. In BASH, I believe it's the same. Then, you don't have to clean up your script. To shut off, use set +xv.
Example:
foo=7
bar=7
PS4='$LINENO: '
set -xv #Begin debugging
if [ $foo = $bar ]
then
echo "foo certainly does equal bar"
fi
set +xv #Debugging is off
if [ $bar = $foo ]
then
echo "And bar also equals foo"
fi
Results:
$ myprog.sh
if [ $foo = $bar ]
then
echo "foo certainly does equal bar"
fi
5: [ 7 = 7 ]
7: echo 'foo certainly does equal bar'
foo certainly does equal bar
set +xv #Debugging is off
And bar also equals foo
Use a function
Define a function instead of using echo:
Example:
function myecho {
if [ ! -z "$DEBUG" ]
then
echo "$*"
fi
}
DEBUG="TRUE"
my echo "Will print out this line"
unset DEBUG
myecho "But won't print out this line"
Use the nop command
The colon (:) is the nop command in BASH. It doesn't do anything. Use an environment variable and define it as either echo or :. When set to a colon, nothing happens. When set to echo, the line prints.
Example:
echo=":"
$echo "This line won't print"
echo="echo"
$echo "But this line will."
Building on Matthew's answer, how about something like this:
myEcho = "/bin/true"
if [ ! "$CRON" ]: then
myEcho = "/bin/echo"
fi
and then use $myEcho instead of echo in your script?
You can do one better. If you setup your crontab as detailed in another answer, you can then check if you are running in cron and only print if you are not. This way you don't need to modify your script at all between different runs.
You should then be able to use something like this (probably doesn't quite work, I'm not proficient in bash):
if [ ! "$CRON" ]; then
echo "Blah blah"
fi
Try set -v at the top to echo each command. To stop echoing change it to set +v.
Not sure if I miss the below solution to use a variable (e.g. debug) at the start of the bash script.
Once you set the debug=true, any conditional-if will enable or disable multiple “echo statements” in bash script.
typeset debug=false # set to true if need to debug
...
if [ $debug == "true" ]; then
echo
echo "Filter"
read
fi
...
if [ $debug == "true" ]; then
echo
echo "to run awk"
fi
Couldn't post a code block in a comment, so I'll post this as an answer.
If you're a perfectionist (like I am) and don't want the last set +x line to be printed... and instead print Success or FAIL, this works:
(
set -e # Stop at first error
set -x # Print commands
set -v # Print shell input lines as they are read
git pull
// ...other commands...
) && echo Success || echo FAIL
It will create a sub process, though, which may be an overkill solution.
If you're running it in cron, why not just dump the output? Change your crontab entry so that it has > /dev/null at the end of the command, and all output will be ignored.

Resources