Простой ответ на оригинальный вопрос
Все это похоже на обычные сценарии оболочки:
# 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
Материал trap
обеспечивает минимальный ущерб, если пользователь решает прервать, убирая временныефайл.Обратите внимание, что старая версия скрипта, если таковая имеется, уже была засорена.Если вы хотите, вы можете организовать создание сценария в другом временном файле и завершить перемещение только тогда, когда вы удовлетворены.Обычно я использую перенаправление ввода / вывода по команде crontab
;вы можете прекрасно указать имя файла в качестве аргумента.
Обратите внимание на экранирование \$ORACLE_HOME
и \$PATH
, которое Уильям Перселл , правильно указанный, должно присутствовать на \$ORACLE_HOME
и(возможно) присутствовать на \$PATH
.Вам нужно решить, хотите ли вы принять cron
-обеспечиваемое (абсолютно минимальное) значение $PATH
(в этом случае вы хотите обратную косую черту) или хотите ли вы использовать текущее значение пользователя $PATH
в cron
скрипт.Либо может быть правильным - просто знайте, что вы выбираете и почему.Помните, что среда, предоставляемая cron
, всегда минимальна;вы получите настройки для PATH, HOME, возможно TZ, возможно USER и, возможно, LOGNAME;это может быть все.Если вы не уверены, попробуйте запустить запись crontab, которая фиксирует окружение в файле:
* * * * * env > /tmp/cron.env
Вероятно, файл окажется маленьким.Не забудьте удалить запись после тестирования.
Одна хорошая вещь, за которую вас рекомендуют:
- Ваш скрипт (a) гарантирует, что он устанавливает средуи (b) запускает простую команду из записи
crontab
, оставляя сценарий для выполнения тяжелой работы.
На мой взгляд, записи в файле crontab
действительно должны быть простымивот так, вызывая специально созданный скрипт для выполнения реальной работы.
Критика предложенного скрипта в пересмотренном вопросе
#!/bin/bash
ORACLE_HOME="/opt/app/oracle/product/11.2.0/dbhome_1"
ORACLE_SID="HEER"
ORACLE_USER="USER1"
ORACLE_PASSWORD="USERPASS"
Пока что проблем нет:
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
Это ужасно повторяющееся, а начинать с добавления - нехорошо.Я бы использовал:
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
{ ... }
применяет перенаправление ввода / вывода к вложенным командам.Обратите внимание, что перед }
.
chmod 755 $PWD/sqlcronprocedure.sh
должна быть точка с запятой или символ новой строки. Поскольку у меня есть переменная для имени файла, я бы использовал ее:
chmod 755 $cronscript
Тогда у нас есть проблема с повторением здесь, плюс мы не убираемся за собой:
crontab -l > $PWD/sqlcorn.sh
echo "0,15,30,45 * * * * $PWD/sqlcronprocedure.sh" >> $PWD/sqlcorn.sh
crontab $PWD/sqlcorn.sh
Таким образом, я бы написал:
crontab=sqlcron.sh
crontab -l > $crontab
echo "0,15,30,45 * * * * $cronscript" >> $crontab
crontab $crontab
rm -f $crontab
Я все еще думаю, что trap
неслишком сложный и должен использоваться в любом скрипте, который создает временные файлы;однако это твой беспорядок, а не мой.Я не уверен, что $PWD
нужен везде;Я оставил это в одном имени, а не в другом.Если вы не указали путь к каталогу, подразумевается $PWD
.Я также отмечаю, что в предложенном вами полном сценарии вы используете немного другое имя сценария, чем в оригинале.Пока имена самосогласованны, проблем нет (а использование переменной помогает обеспечить согласованность), но будьте осторожны.
Я не уверен, что на самом деле сделал бы это так, но вы также можете избежать временного файла, используя:
{
crontab -l
echo "0,15,30,45 * * * * $cronscript"
} | (sleep 1; crontab -)
Это собирает текущее значение и добавляет дополнительную строку, передавая все это в сценарий, который спит на секунду (чтобы позволить первой части временизавершено) до подачи результатов обратно в crontab
.Вопрос в том, насколько надежна задержка в одну секунду, в основном.Это, вероятно, хорошо, но не гарантировано.Временный файл надежен на 100% - я бы использовал его, потому что он не более сложный.(Я мог бы использовать круглые скобки вокруг первой пары команд; я мог бы использовать скобки вокруг второй пары команд, но мне нужно было бы добавить точку с запятой между -
и )
, которая заменяется на }
.)
Обратите внимание, что мое первоначальное предложение было осторожным, чтобы гарантировать, что даже если сценарий запускался несколько раз, в файле crontab будет только одна запись для процесса.Ваши варианты не уверены в идемпотентности.