Simple answer to the original question
Everything looks like a normal shell script:
# Clobber previous edition of script! cronscript=$HOME/scripts/cronSqlprocedure.sh cat <<EOF > $cronscript export ORACLE_HOME=/opt/app/oracle/product/11.2.0/dbhome_1 export PATH=\$ORACLE_HOME/bin:\$PATH export ORACLE_SID=HEER ...and whatever else is needed... EOF chmod u+x $cronscript # Add to crontab tmp=${TMPDIR:-/tmp}/xyz.$$ trap "rm -f $tmp; exit 1" 0 1 2 3 13 15 crontab -l | sed '/cronSqlprocedure.sh/d' > $tmp # Capture crontab; delete old entry echo "0,15,30,45 * * * * $cronscript" >> $tmp crontab < $tmp rm -f $tmp trap 0
The trap material provides minimal damage if the user decides to interrupt by clearing the temporary file. Please note that the old version of the script, if any, has already been downed. If you wanted, you could arrange for a script to be created in another temporary file and only complete the movement when you are satisfied. I usually use I / O redirection in the crontab command; you can perfectly specify the file name as an argument.
Note the escapes on \$ORACLE_HOME and \$PATH that William Pursell correctly indicated that he should be present at \$ORACLE_HOME and should (possibly) be present at \$PATH . You need to decide whether you want to accept the cron -supported (completely minimal) value of $PATH (in this case you want the backslash) or want to use the current value of the user $PATH in the cron script. Anyone can be right - just know what you choose and why. Remember that the environment provided by cron is always minimal; You will get the settings for PATH, HOME, maybe TZ, maybe USER and maybe LOGNAME; that could be all. If you're not sure, try running a crontab entry that captures the environment in the file:
* * * * * env > /tmp/cron.env
You will probably find that the file is small. Do not forget to delete the entry after testing.
Itβs good that you deserve praise for:
- Your script (a) ensures that it installs the environment, and (b) runs a simple command from the
crontab entry, leaving the script to do the hard work.
In my opinion, the entries in the crontab file should really be the same as when calling a specially created script to do the real work.
Criticism of proposed script in revised question
#!/bin/bash ORACLE_HOME="/opt/app/oracle/product/11.2.0/dbhome_1" ORACLE_SID="HEER" ORACLE_USER="USER1" ORACLE_PASSWORD="USERPASS"
No problem so far:
echo "export ORACLE_HOME=$ORACLE_HOME" >> $PWD/sqlcronprocedure.sh echo "export PATH=\$ORACLE_HOME/bin:\$PATH" >> $PWD/sqlcronprocedure.sh echo "export ORACLE_SID=$ORACLE_SID" >> $PWD/sqlcronprocedure.sh echo "rTmpDir=/tmp" >> $PWD/sqlcronprocedure.sh echo "sqlplus -s $ORACLE_USER@$ORACLE_SID/$ORACLE_PASSWORD > $rTmpDir/deleteme.txt 2>&1 <<EOF" >> $PWD/sqlcronprocedure.sh echo " select 1 from dual;" >> $PWD/sqlcronprocedure.sh echo " execute prvsapupd(1000,14);" >> $PWD/sqlcronprocedure.sh echo "EOF" >> $PWD/sqlcronprocedure.sh
This repeats horribly, and starting with append is not very good. I would use:
cronscript=$PWD/sqlcronprocedure.sh { echo "export ORACLE_HOME=$ORACLE_HOME" echo "export PATH=\$ORACLE_HOME/bin:\$PATH" echo "export ORACLE_SID=$ORACLE_SID" echo "rTmpDir=/tmp" echo "sqlplus -s $ORACLE_USER@$ORACLE_SID/$ORACLE_PASSWORD > $rTmpDir/deleteme.txt 2>&1 <<EOF" echo " select 1 from dual;" echo " execute prvsapupd(1000,14);" echo "EOF" } > $cronscript
{ ... } applies I / O redirection to the attached commands. Note that there must be a semicolon or a new line before } .
chmod 755 $PWD/sqlcronprocedure.sh
Since I have a variable for the file name, I would use it:
chmod 755 $cronscript
Then we have a problem with repeating here, plus not cleaning up after ourselves:
crontab -l > $PWD/sqlcorn.sh echo "0,15,30,45 * * * * $PWD/sqlcronprocedure.sh" >> $PWD/sqlcorn.sh crontab $PWD/sqlcorn.sh
So I would write:
crontab=sqlcron.sh crontab -l > $crontab echo "0,15,30,45 * * * * $cronscript" >> $crontab crontab $crontab rm -f $crontab
I still think trap not too complicated and should be used in any script that creates temporary files; however, this is your mess, not mine. I'm not sure if $PWD needed everywhere; I left him with one name and not another. If you do not specify a directory path, $PWD assumed. I also note that you use a slightly different script name in the full script you proposed from the one in the original. As long as the names are self-consistent, there is no problem (and using a variable helps ensure consistency), but be careful.
I'm not sure that I actually do it this way, but you can also avoid a temporary file using:
{ crontab -l echo "0,15,30,45 * * * * $cronscript" } | (sleep 1; crontab -)
This collects the current value and adds an extra line, feeding it all into a script that sleeps for a second (to complete the first part of the time) before returning the results back to crontab . There's a question about how reliable one second delay is, basically. This is probably good, but not guaranteed. The temporary file is 100% reliable - I would use it because it is no more complicated. (I could use parentheses around the first pair of commands, I could use braces around the second pair of commands, but I would need to add a colon between - and ) , which is replaced by } .)
Please note that my initial sentence was careful to ensure that even if the script was run multiple times, there would be only one entry in the crontab file for the process. Your options do not guarantee idempotency.