How to throw a user-defined exception in a ksh script - exception

CHECK_FTP=`cat ftp_test.txt | grep 'Login incorrect.'`
if [ -n "$CHECK_FTP" ]; then
" login is incorrect, please correct the password/username "
cd unable_to_connect_to_remote_server
In the above code I need to raise a user defined exception, please note I cannot use the command exit, since it exits the script but it does not fail the script.

Related

Mysql cli not returning data in bash script run by crontab

I have a bash script that is executed via a cron job
#!/bin/bash
# abort on errors
set -e
ABS_DIR=/path/
# extract the creds for the mysql db
DB_USER="USERNAME"
DB_PASS="PASSWORD"
function extract_data() {
file=$2
sql_query=`cat $ABS_DIR/$1`
data=`mysql -u $DB_USER --password="$DB_PASS" -D "database" -e "$sql_query" | tail -n +2`
echo -e "Data:"
echo -e "$data"
}
extract_data "sql_query.sql" "log.csv"
When running it manually with bash extract.sh the mysql cmd fetches the data correctly and I see the echo -e "$data" on the console.
When running the script via a cron job
* 12 * * * /.../extract.sh > /.../cron_log.txt
then I get an empty line saved to the cron_log.txt file!?
This is a common problem; a script behaves differently when run from user shell and when run from crontab. The cause is typically due to differences in the environment variables in the user shell, and in the crontab shell; by default, they are not the same.
To begin debugging this issue, you could direct stderr as well as stdout from crontab, hopefully to capture an error message:
extract.sh &> /.../cron_log.txt
(notice the &)
Also: you have three dots (/.../) -- that is likely a typo, could also be the cause.

Catch an error in piped MySQL command (bash)

Is there any way to avoid the first eval for code below? I tried to play with ${LASTPIPE[0]} and such things but it was way too complicated for me. For instance when I tried to inject code with semicolon ($MYSQLCOMMAND; if ...) it broke my output to the pipe. I spent more than 8 hours wandering StackOverflow just to give up and write one more SQL command without pipe. Don't want to publish bad written code.
MYSQLQUERY="select * from $TABLENAME"
MYSQLTOPTIONS="--defaults-extra-file=$EXTRA -h $HOSTNAME -D $DBNAME -N -e"
MYSQLCOMMAND='mysql $MYSQLTOPTIONS "$MYSQLQUERY"'
# Exit immediately if something wrong with MySQL command
if eval "$MYSQLCOMMAND > /dev/null" ; then : ; else \
printf "Script returned non-zero exit code: %s\n" "$?" ; exit $?; fi
# Count rows for valid JSON output
ROWS=0
eval $MYSQLCOMMAND | \
while read ; \
do
((ROWS++))
done
(rest of the code generates JSON with calling the same
eval ... while read... and verified by https://jsonlint.com/)
Also I'd like to hear any your comment on the code since I'm not an experienced bash coder.

How to import shell functions from one file into another?

I have the shell script:
#!/bin/bash
export LD=$(lsb_release -sd | sed 's/"//g')
export ARCH=$(uname -m)
export VER=$(lsb_release -sr)
# Load the test function
/bin/bash -c "lib/test.sh"
echo $VER
DISTROS=('Arch'
'CentOS'
'Debian'
'Fedora'
'Gentoo')
for I in "${DISTROS[#]}"
do
i=$(echo $I | tr '[:upper:]' '[:lower:]') # convert distro string to lowercase
if [[ $LD == "$I"* ]]; then
./$ARCH/${i}.sh
fi
done
As you can see it should run a shell script, depending on which architecture and OS it is run on. It should first run the script lib/test.sh before it runs this architecture and OS-specific script. This is lib/test.sh:
#!/bin/bash
function comex {
which $1 >/dev/null 2>&1
}
and when I run it on x86_64 Arch Linux with this x86_64/arch.sh script:
#!/bin/bash
if comex atom; then
printf "Atom is already installed!"
elif comex git; then
printf "Git is installed!"
fi
it returned the output:
rolling
./x86_64/arch.sh: line 3: comex: command not found
./x86_64/arch.sh: line 5: comex: command not found
so clearly the comex shell function is not correctly loaded by the time the x86_64/arch.sh script is run. Hence I am confused and wondering what I need to do in order to correctly define the comex function such that it is correctly loaded in this architecture- and OS-dependent final script.
I have already tried using . "lib/test.sh" instead of /bin/bash -c "lib/test.sh" and I received the exact same error. I have also tried adding . "lib/test.sh" to the loop, just before the ./$ARCH/${i}.sh line. This too failed, returning the same error.
Brief answer: you need to import your functions using . or source instead of bash -c:
# Load the test function
source "lib/test.sh"
Longer answer: when you call script with bash -c, a child process is created. This child process sees all exported variables (including functions) from parent process. But not vice versa. So, your script will never see comex function. Instead you need to include script code directly in current script and you do so by using . or source commands.
Part 2. After you "sourced" lib/test.sh, your main script is able to use comex function. But arch scripts won't see this function because it is not exported to them. Your need to export -f comex:
#!/bin/bash
function comex {
which $1 >/dev/null 2>&1
}
export -f comex

how to output success or failure of cp command to file

I'm going to be running a shell script containing a CP command using a scheduled cron job. I would like to include in the script something to output to a log file whether the copy was successful or failed.
Appreciate any advice in advance.
Thanks
You can check the return code of cp. From the cp man page:
EXIT STATUS
The cp utility exits 0 on success, and >0 if an error occurs.
The exit code of the last operation is stored in the special variable $?, so you can do something like this:
cp .. ..
echo $? >> outputfile
Most likely, you'll want to have some sort of "custom" error message. For that purpose, you can check the value of $?
cp .. ..
if [ $? -ne 0 ]
then
echo "there was an error" >> outputfile
fi
I hope that gets you started.

Why does "exec" gives "child exited abnormally" in this code?

I am running this code in tcl:-
set version [exec grep "INTERNAL VERSION:" mojave.log | sed -n -e "s/INTERNAL VERSION: //g" > xor.diff]
set p [exec diff ../log.warning.diff ../log.warning.gold >> xor.diff ]
For the last line it gives the following error after doing some diff:-
> RULE-311 WARNING: Gdsii layer number 85 datatype 0 has already been defined
> TCL-11 WARNING: Command "check quartz drc" is overridden, Quality Of
> TCL-11 WARNING: Command "delete marker quartz" is overridden, Quality Of
> TCL-11 WARNING: Command "import marker quartz" is overridden, Quality Of
> TCL-11 WARNING: Command "mojave! run filter log" is overridden, Quality Of
> TCL-11 WARNING: Command "run quartz gui" is overridden, Quality Of Results
> TCL-11 WARNING: Command "ui! mojave draw rectangle" is overridden, Quality
> TCL-11 WARNING: Command "ui! mojave set_context" is overridden, Quality Of
> TCL-12 WARNING: Overridden command "mojave! run filter log" is used,
child process exited abnormally
while executing
"exec diff ../log.warning.diff ../log.warning.gold 2> xor.diff "
invoked from within
"set p [exec diff ../log.warning.diff ../log.warning.gold 2> xor.diff ]"
(file "test.tcl" line 4)
invoked from within
"source test.tcl"
And it is not writing anything in "xor.diff" file.
exec returns an error if the command returns non-zero or if it sends anything to stderr. There's a very thorough discussion of using catch with exec at http://wiki.tcl.tk/exec
diff (and comm) exits nonzero if any differences are found, so you can redirect the output to use them as "did this change?" tests. For Tcl you'll want to use the `|| :' idiom to ignore the exit status.
P.S. "useless use of grep"... sed -n -e '/INTERNAL VERSION: /s//gp'