编写shell脚本以安装cron作业



这是我第一次编写shell脚本,在给定的时间线中我几乎没有什么信息。虽然我正在阅读不同的教程,但我想问我在这里想要什么。

我想写一个shell脚本,它在任何机器上编辑cronjob,每15分钟添加一个要执行的新脚本。所以基本上我必须添加一个条目

0,15,30,45 * * * * /home/personal/scripts/cronSqlprocedure.sh

我想要的外壳脚本

  • 它将首先更改cronSqlprocedure.sh的权限/执行权限
  • 编辑现有的cron作业,并将此新条目添加到其中

如果可能的话,我也想通过shell脚本编写cronSqlprocedure,因为它需要两个变量,这些变量可能会随着系统的不同而变化。

export ORACLE_HOME=/opt/app/oracle/product/11.2.0/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH
export ORACLE_SID=HEER

必须为cronSqlprocedure.sh中的每台机器配置这些线路

#!/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 another_script(1000,14);" >> $PWD/sqlcronprocedure.sh
echo "EOF" >> $PWD/sqlcronprocedure.sh
chmod 755 $PWD/sqlcronprocedure.sh
crontab -l > $PWD/sqlcorn.sh
echo "0,15,30,45 * * * * $PWD/sqlcronprocedure.sh" >> $PWD/sqlcorn.sh
crontab $PWD/sqlcorn.sh

原始问题的简单答案

这一切看起来像是例行的shell脚本:

# 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命令上使用I/O重定向;您可以很好地提供文件名作为参数。

注意William Pursell正确指出的$ORACLE_HOME$PATH上的转义应该存在于$ORACLE_HOME上,并且应该(也许)存在于$PATH上。您需要决定是使用cron提供的(完全最小的)$PATH值(在这种情况下,您需要反斜杠),还是在cron脚本中使用用户的当前值$PATH。任何一种都可能是正确的——只要知道你选择了哪一种以及为什么。请记住,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

这是非常重复的,并且从append开始是不好的。我会使用:

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

{ ... }将I/O重定向应用于包含的命令。请注意,}之前必须有一个分号或换行符。

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文件中也只有一个进程条目。您的变体不能确保幂等性。

我发现了一个类似的问题:以编程方式编辑crontab并强制守护进程刷新

更改文件的权限是典型的shell脚本,有许多可用资源。

对于cronjob,您将希望本质上与crontab程序接口,并为其提供全新的cron文件。您可以首先检索已经配置的cron作业,将您的作业添加到列表中,然后再次调用crontab为其提供新的输入文件。

有关更多信息,请参阅crontab的手册页。

#/bin/shSCRIPT=/home/personal/scripts/cronSqlprocedure.sh#写剧本。cat>脚本<lt;'EOF'export ORACLE_HOME=/opt/app/ORACLE/product/11.2.0/dbhome_1export PATH=$ORACLE_HOME/bin:$PATHexport ORACLE_SID=HEEREOF#使脚本可执行chmod+x$脚本#将此脚本添加到现有的crontab中。这取决于#sed支持-i。如果没有,可能最容易#编写一个执行编辑的简单脚本,并将VISUAL设置为该脚本如果crontab-l|grep$SCRIPT>/dev/null;然后VISUAL="ed-i-e"\$a\0,15,30,45***'$SCRIPT'"'crontab-efi

创建一个cron.d文件,如/etc/cron.d/my-sql-proc

0,15,30,45  *  *  *  *  root  /home/personal/scripts/cronSqlprocedure.sh
                        # 
                        # run-as user

@Patrickunix.stackexchange.com:回答

我建议使用/etc/cron.d而不是crontab

您可以将文件放置在/etc/cron.d中,这些文件的行为类似于crontab条目。尽管格式略有不同。

帕特里克指出,这可能不适用于所有系统,但他的答案既被接受,也获得了最多的选票。它在debian 9(伸展)上对我很有效。

来源:https://unix.stackexchange.com/questions/117244/installing-crontab-using-bash-script#117254

最新更新