setting crontab from bash script - linux

I have written the following script but i am getting error sqlcorn.sh: No such file or directory
here is the script
#!/bin/bash
ORACLE_HOME="/opt/app/oracle/product/11.2.0/dbhome_1"
ORACLE_SID="HEER"
ORACLE_USER="USER1"
ORACLE_PASSWORD="USERP"
echo "export ORACLE_HOME=$ORACLE_HOME" >> sqlcronprocedure.sh
echo "export PATH=\$ORACLE_HOME/bin:\$PATH" >> sqlcronprocedure.sh
echo "export ORACLE_SID=$ORACLE_SID" >> sqlcronprocedure.sh
echo "rTmpDir=/tmp" >> sqlcronprocedure.sh
echo "sqlplus -s $ORACLE_USER#$ORACLE_SID/$ORACLE_PASSWORD > $rTmpDir/deleteme.txt 2>&1 <<EOF" >> sqlcronprocedure.sh
echo " select 1 from dual;" >> sqlcronprocedure.sh
echo " execute someproc(1000,14);" >> sqlcronprocedure.sh
echo "EOF" >> sqlcronprocedure.sh
chmod 755 sqlcronprocedure.sh
crontab -l > sqlcron.sh
echo "0,15,30,45 * * * * /sqlcronprocedure.sh" >> sqlcron.sh
crontab sqlcorn.sh
This is my first ever script. so i apologize if things are too obvious to ask

The real problem: You misspelled the file name on the crontab command. Change it from:
crontab sqlcorn.sh
to
crontab sqlcron.sh
Some more comments on your code:
Your multiple echo commands are better written as a "here document". Rather than this:
echo "export ORACLE_HOME=$ORACLE_HOME" >> sqlcronprocedure.sh
echo "export PATH=\$ORACLE_HOME/bin:\$PATH" >> sqlcronprocedure.sh
echo "export ORACLE_SID=$ORACLE_SID" >> sqlcronprocedure.sh
echo "rTmpDir=/tmp" >> sqlcronprocedure.sh
echo "sqlplus -s $ORACLE_USER#$ORACLE_SID/$ORACLE_PASSWORD > $rTmpDir/deleteme.txt 2>&1 <<EOF" >> sqlcronprocedure.sh
echo " select 1 from dual;" >> sqlcronprocedure.sh
echo " execute someproc(1000,14);" >> sqlcronprocedure.sh
echo "EOF" >> sqlcronprocedure.sh
you can do this:
cat <<EOF >sqlcronprocedure.sh
export ORACLE_HOME=$ORACLE_HOME
export PATH=\$ORACLE_HOME/bin:\$PATH
export ORACLE_SID=$ORACLE_SID
rTmpDir=/tmp
EOF
cat <<END_OF_SCRIPT >sqlcronprocedure.sh
export ORACLE_HOME=$ORACLE_HOME
export PATH=\$ORACLE_HOME/bin:\$PATH
export ORACLE_SID=$ORACLE_SID
rTmpDir=/tmp
sqlplus -s $ORACLE_USER#$ORACLE_SID/$ORACLE_PASSWORD > $rTmpDir/deleteme.txt 2>&1 <<EOF
select 1 from dual;
execute someproc(1000,14);
EOF
END_OF_SCRIPT
which is a bit easier to read. (Your version wasn't incorrect, just hard to read and error-prone; you have to get the >> sqlcronprocedure.sh right on eacn and every line.)
Note: You use >> to build sqlcronprocedure.sh, which appends to the existing sqlcronprocedure.sh if it exists. I don't think that's what you want to do; you probably want to create the file from scratch. My code assumes you want to create the file rather than appending to it.
The last part of your script:
crontab -l > sqlcron.sh
echo "0,15,30,45 * * * * /sqlcronprocedure.sh" >> sqlcron.sh
crontab sqlcorn.sh
is fine except for two things.
First sqlcron.sh is not a good name for the file, since it's not a shell script; just call it sqlcron. The system doesn't care, but you should.
Second, the misspelling I mentioned above.

you need to specify the full path to sqlcron.sh in your script...

Related

How to preceed the output generated by "exec &" with a time/Date in linux bash scripts?

I have the following script file that writes files to s3 from a local file system:
#!/bin/bash
CURR_DIR=`dirname $0`
SCRIPT_NAME="$(basename $0)"
LOG_FILE=$(echo $SCRIPT_NAME | cut -f 1 -d '.')
TODAY=$(date '+%Y-%m-%d')
NOW=$(date -d "$(date +%Y-%m-%d)" +%Y"-"%m"-"%d)
LOG_PATH="$CURR_DIR"/logs/"$LOG_FILE"-$TODAY.log
LOG="[$(date '+%Y-%m-%d %H:%M:%S,%3N')] INFO {$LOG_FILE} -"
ERROR_LOG="[$(date '+%Y-%m-%d %H:%M:%S,%3N')] ERROR {$LOG_FILE} -"
BUCKET="s3.bucket.example"
OUT_FOLDER="path/to/folderA"
S3_PUSH="s3://$BUCKET/$OUT_FOLDER"
exec &>> $LOG_PATH
echo "$LOG Copying files to local out folder..." >> $LOG_PATH
cp /path/to/folderA/*.* /path/to/folderB
echo "$LOG Command returned code:" $?
if [ "$(ls -A path/to/folderA/)" ]; then
FILES="$(ls path/to/folderA/*)"
for file in $FILES ; do
echo "$LOG File $file found for sync" >> $LOG_PATH
echo "$LOG Pushing $file to S3 /Folder..." >> $LOG_PATH
echo -n "$LOG " ; s3cmd put -c /home/config/.s3cfg "$file" "$S3_PUSH"/
echo "$LOG Command returned code:" $?
echo "$LOG Copying $file to local backup..." >> $LOG_PATH
mv "$file" /path/to/folderA/backup/
echo "$LOG Command returned code:" $? >> $LOG_PATH
RCC=$?
if [ $? -eq 0 ]
then
echo "$LOG Command returned code:" $?
else
echo "$ERROR_LOG Command returned code:" $?
fi
done
else
echo "$LOG No files found for sync." >> $LOG_PATH
fi
And the output is coming out in a specific grok pattern needed for me to parse this output as logs into Elastic Search, however the line 27 output is as follows:
[2021-09-02 08:15:25,629] INFO {TestGrokScriptPattern} - upload: '/path/to/folderA/File.txt' -> 's3://s3.bucket.example/Path/To/Bucket/File.txt' [1 of 1]
0 of 0 0% in 0s 0.00 B/s done
that upload and 0 of 0 0%... Line is created by the exec & command executed on line 16.
How can I get that output to not go to the next line without the date, time and script name preceeding it in order to not break the log pattern I am trying to create?
Rather than redirect output on each line, you can wrap the body of the script in a single block and then handle the output of the entire block in one place. You can then process that output with the stream editor sed. For example:
if true; then # Always true. Just simplifies redirection.
echo "Doing something..."
command_with_output
command_with_more_output
echo "Done."
fi | sed "s/^/${LOG}/" > ${LOG_PATH} 2>&1
The sed expression means: Substitute (s) the beginning of each line (^) with the contents of the LOG variable.
Using 2>&1 at the end also eliminates the need for the exec &>> $LOG_PATH command.

How to replace '>> $log_file 2>&1' from all files

In my files commands are like :
File1.sh:
log_file='20210101'
echo -e "\n Output is \n" >> $log_file 2>&1
File2.sh
echo "Something"
log_file='20210102'
hive -e -f my_file_name.hql >> $log_file 2>&1
File3.sh
cat myfile
echo "something"
ehco "new line"
log_file='2021-01-01_23_59_59'
hive -e "Select * from tables' >> $log_file 2>&1
I am looking for a command to remove the line where defined variable 'log_file' from all the files
AND
remove only '>> $log_file 2>&1' part from all the files
Output in files:
File1.sh:
echo -e "\n Output is \n"
File2.sh
echo "Something"
hive -e -f my_file_name.hql
File3.sh
cat myfile
echo "something"
ehco "new line"
hive -e "Select * from tables'
I tried multiple ways with sed but nothing worked, few of them are :
I tried :
sed -e 's/*[>> $]log_file//g' test.sh
sed -e 's/*[>> $]log_file[ 2>&1]//g' test.sh
sed -e 's/\>\> \$log_file \2\>$//' test.sh
sed -e 's/">> $log_file 2>&1"/""/g' test.sh
This sed command is a two-step process, and makes a backup of all files (just in case); on my machine (and with the 3 samples you posted) it does the right thing:
sed -i.bak -e '/^log_file=/d' -e 's/>> \$log_file 2>&1//g' File*

`newline' unexpected when run shell script

Im new to unix command. I would like to execute jasper file P70152R1 and pass busDt param to that file.
Currently hit this error >>> line 51: syntax error at line 53: `newline' unexpected
Can anyone help me to check my shell script.
Below is my script:
echo "*********************************************************"
echo "* xxxxxxxxxxxxxxxxxxxxxxxxx *"
echo "*********************************************************"
echo
echo "*********************************************************************************"
echo "* xxxxxxxxxxxxxxxxxxxxxxxx *"
echo "* UP *"
echo "* P700152R1 - AAAAAAAAAAAAAAAAAAA REPORT *"
echo "* P700152R2 - BBBBBBBBBBBBBBBBBBB REPORT *"
echo "* P700152R3 - CCCCCCCCCCCCCCCCCCC REPORT *"
echo "* (JP700152) *"
echo "* FREQUENCY : DAILY *"
echo ****************************************************************************"
echo
cd $MAIN/CWJCL/ACQ
export JCL=$MAIN/CWJCL/ACQ
export PRM=$MAIN/CWPRM/ACQ:$MAIN/CWPRM/CMN
export JAS=$MAIN/CWRPT/ACQ
export rptDir=$MAIN/ACQ/DAILYRPT
export LOG=$MAIN/CWLOG/ACQ
echo "Start Time and Date : \c" &&date
echo
JP70152=`date +%Y%m%d%H%M%S`
$JCL/strtJob $JP70152 JP70152
# Classpath
. $JCL/SETENV
#export CLASSPATH=$CLASSPATH:$PRM:$LIB/acq-1.0.jar
export CLASSPATH=$CLASSPATH:$PRM:"$MAIN/CWLIB/classes/acq"
# Get Business Date
echo "set heading off;" > $LOG/busDtSel.sql
echo "spool $LOG/date.log;" >> $LOG/busDtSel.sql
echo "ALTER SESSION SET CURRENT_SCHEMA=CCPS;" >> $LOG/busDtSel.sql
echo "SELECT 'CURRENT-BUSS-DATE:'||F9_AP008_BUS_DT FROM AP008;" >> $LOG/busDtSel.sql
echo "spool off;" >> $LOG/busDtSel.sql
echo "EXIT;" >> $LOG/busDtSel.sql
echo
$JCL/CONNAM.sh $LOG/busDtSel.sql $LOG/sel_day
a=$?
if [ ! $a -eq 0 ]
then
return $a
fi
tmpDt=`grep CURRENT-BUSS-DATE $LOG/date.log`
busDt=${tmpDt##*:}
# run program.
yyyymmdd=`date +%Y%m%d`
$JAVA_HOME/bin/java my.com.eprotea.report.JRGenerator -Ttxt -J$JAS/P70152R1.jasper -DACQ -O$rptDir/P70152R1.rpt -P<BUS-DATE:$busDt>
##########$JAVA_HOME/bin/java my.com.eprotea.report.JRGenerator -Ttxt -J$JAS/P70152R2.jasper -DACQ -O$rptDir/P70152R2.rpt -P<BUS-DATE:$busDt>
##########$JAVA_HOME/bin/java my.com.eprotea.report.JRGenerator -Ttxt -J$JAS/P70152R3.jasper -DACQ -O$rptDir/P70152R3.rpt -P<BUS-DATE:$busDt>
a=$?
echo $a
if [ ! $a -eq 0 ]
then
return $a
fi
echo
echo
echo
$JCL/endJob $JP70152 JP70152
echo "End Time and Date : \c" &&date
echo
return $a
Really appreciate your help. Thanks id advance !
The < and > characters have a special meaning in bash. You used them in
echo "set heading off;" > $LOG/busDtSel.sql
to redirect the output of the echo to $LOG/busDtSel.sql.
In your line 53, you do:
$JAVA_HOME/bin/java my.com.eprotea.report.JRGenerator options -P<BUS-DATE:$busDt>
That means that the last argument for the JRGenerator is -P, that the stdin comes from the file BUS-DATE:$busDt and that stdout goes to, ehm, nothing. There is a new-line. That is unexpected for bash, because it expected a destination for stdout. Hence the error message.
The solution is to use quotes:
$JAVA_HOME/bin/java my.com.eprotea.report.JRGenerator options "-P<BUS-DATE:$busDt>"
There are other issues in your script as well; for example: there is a line with:
echo ************************************"
which should obviously be:
echo "************************************"
I think that this might be a mistake in putting the script in the question, because this generates a different error message for me.
You forgot to add a " at the beginning of a line and therefore screws up everything:
echo "*********************************************************************************"
echo "* xxxxxxxxxxxxxxxxxxxxxxxx *"
echo "* UP *"
echo "* P700152R1 - AAAAAAAAAAAAAAAAAAA REPORT *"
echo "* P700152R2 - BBBBBBBBBBBBBBBBBBB REPORT *"
echo "* P700152R3 - CCCCCCCCCCCCCCCCCCC REPORT *"
echo "* (JP700152) *"
echo "* FREQUENCY : DAILY *"
HERE -> echo ****************************************************************************"
Hi you are using > operator at the end of your java command. Better use a escape sequence to overcome this issue. See below correct expression.
$JAVA_HOME/bin/java my.com.eprotea.report.JRGenerator -Ttxt -J$JAS/P70152R1.jasper -DACQ -O$rptDir/P70152R1.rpt -P\<BUS-DATE:$busDt\>
or, you can try like below as Ljm provided in his answer:-
$JAVA_HOME/bin/java my.com.eprotea.report.JRGenerator -Ttxt -J$JAS/P70152R1.jasper -DACQ -O$rptDir/P70152R1.rpt "-P<BUS-DATE:$busDt>"

Better way to write a script for better error detection, time and resource efficiency?

I need suggestions on how to improve the below script for better efficiency ( both time and resource, and for better error detection). Here is a simple description on what the script does:
Functionality: The script runs in crontab for "ins" user very minute, searches for a .DAT file in "input path". If it finds the .dat file, moves it to "working directory", executes it as a batch, and after completion of the execution of .dat file moves it to "output folder". The .dat file contains a series a similar commands to insert numbers into database.
#!/usr/bin/ksh
def_path="/apps/ins/"
env_path="/apps/ins/eir/bin"
input_path="/apps/ins/eir/batch/input/"
work_path="/apps/ins/eir/batch/working/"
output_path="/apps/ins/eir/batch/output/"
moved_path="/apps/ins/eir/batch/processed/"
log="/apps/ins/BLA/log/"
date=`date '+%d%b%y'`
cd $input_path
listcount=`ls -rt *.dat |wc -l`
list=`ls -rt *.dat`
echo "`date +%H:%M:%S`| Total No of DAT files available are # $listcount #\nName of the files are...\n $list " >> $log/$date.log 2>&1
if [[ -e $def_path/.bla_processing ]];
then
echo "`date +%H:%M:%S`| Script is already running" >> $log/$date.log 2>&1
exit
fi
for fname in `ls *.dat | awk -F. '{print $1}'`
do
touch $def_path/.bla_processing
mv $input_path/$fname.dat $work_path/$fname.dat
echo "##################################################" >> $log/$date.log 2>&1
echo "## Filename = $fname.dat ## Time = `date +%H:%M:%S` ##" >> $log/$date.log 2>&1
echo "##################################################" >> $log/$date.log 2>&1
cd $env_path
. /apps/ins/.profile >> $log/$date.log 2>&1
echo "Username is `whoami`" >> $log/$date.log 2>&1
$env_path/mip_cmd EXECUTE:$work_path/$fname.dat,$output_path/$fname.out,100; >> $log/$date.log 2>&1
sleep 2
echo "`date +%H:%M:%S`| Moving the file *** $fname.dat *** to path |$moved_path|" >> $log/$date.log 2>&1
mv $work_path/$fname.dat $moved_path/$fname.dat.moved
cmd_exec=`cat $output_path/$fname.out |grep ":" |wc -l`
echo "`date +%H:%M:%S`| Total commands executed are `expr $cmd_exec / 2`" >> $log/$date.log 2>&1
echo "`date +%H:%M:%S`| Total Sucessfully executed commands are `cat $output_path/$fname.out |grep "C1:00000;" |wc -l`" >> $log/$date.log 2>&1
echo "--------------------------------------------------" >> $log/$date.log 2>&1
echo "#### SCRIPT WILL PROCESS THE NEXT FILE ###########" >> $log/$date.log 2>&1
echo "--------------------------------------------------" >> $log/$date.log 2>&1
echo "" >> $log/$date.log 2>&1
rm $def_path/.bla_processing
exit
done
Since you are using "$def_path/.bla_processing" as a form of lock, you should probably check its existense first thing before you proceed with the rest of the script.
Also, "touch $def_path/.bla_processing" and "rm $def_path/.bla_processing" could be moved out of the for loop.
What your code is doing now is, only the first file is processed, and the script will exit. So the call to "exit" in the end of the for loop is not necessary.
As an example (after applying the above suggestions):
touch $def_path/.bla_processing
for fname in `ls *.dat | awk -F. '{print $1}'`
....
# remove the call to exit
done
rm $def_path/.bla_processing

My error messages in terminal blink rather than stay, how can i get it to stay?

I have a basic menu that completes tasks that have already been set to me, i have the menu to show up and the functions to work, however, when the user chooses option 4, the results only blink in the terminal for a split second, and also if they choose an incorrect value, the error message blinks, i need both of them to stay put. Any ideas?
#!/bin/bash
#
# Script to perform some simple tasks
#
chmod 755 TaskB.sh
while:
do
clear
echo "*********************"
echo "* Tools *"
echo "*********************"
echo "* [1] Install gnome-disk-utility and gparted *"
echo "* [2] Create CET103Demo.txt *"
echo "* [3] Delete CET103Demo.txt *"
echo "* [4] Search BASH *"
echo "* [0] Exit/Stop *"
echo "*********************"
echo -n "Enter your menu choice [0-4]: "
read yourch
case $yourch in
1) sudo apt-get install gparted gnome-disk-utility ;;
2) cat > Desktop/CET103Demo.txt;;
3) rm Desktop/CET103Demo.txt;;
4) grep -H -r "BASH" /home/mintuser/.profile ;;
0) exit 0;;
*) echo "Oooops!!! Please select choice 1,2,3,4 or 0";
echo "Press Enter to continue..."; read ;;
esac
done
I haven't used bash in a while but try this:
#!/bin/bash
#
# Script to perform some simple tasks
#
chmod 755 TaskB.sh
while:
do
clear
echo "*********************"
echo "* Tools *"
echo "*********************"
echo "* [1] Install gnome-disk-utility and gparted *"
echo "* [2] Create CET103Demo.txt *"
echo "* [3] Delete CET103Demo.txt *"
echo "* [4] Search BASH *"
echo "* [0] Exit/Stop *"
echo "*********************"
echo -n "Enter your menu choice [0-4]: "
read yourch
case $yourch in
1) sudo apt-get install gparted gnome-disk-utility ;;
2) cat > Desktop/CET103Demo.txt;;
3) rm Desktop/CET103Demo.txt;;
4) grep -H -r "BASH" /home/mintuser/.profile ;;
0) exit 0;;
*) echo "Oooops!!! Please select choice 1,2,3,4 or 0" ;;
esac
read -p "Press [Enter] to continue..."
done
read -p "Press [Enter] to exit..."

Resources