linux - 编写Shell脚本以安装cron作业

标签 linux bash shell cron

这是我第一次编写Shell脚本,并且在给定的时间轴上了解的信息很少。虽然我正在阅读不同的教程,但我还是想问一下我想要什么。

我想编写一个Shell脚本,该脚本可在任何计算机上编辑cronjob,并添加一个每15分钟执行一次的新脚本。所以基本上我必须添加一个条目
0,15,30,45 * * * * /home/personal/scripts/cronSqlprocedure.sh
我在shell脚本中想要什么

  • 它将首先更改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值(完全最小)(在这种情况下,您需要反斜杠),还是要在$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
    

    这是非常重复的,以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文件中也只有一个条目用于该过程。您的变体不能确保幂等性。

    关于linux - 编写Shell脚本以安装cron作业,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9083467/

    相关文章:

    c - 抢占、pthread_spin_lock 和原子内置

    bash - 字符串检测时退出尾部

    linux - 为什么shell会在这种情况下启动另一个shell进程?

    linux - 使用 sed 在包含两个特定字符串的行中添加字符

    bash - 开始时使用 echo -n 命令的有趣行为

    mysql - 使用shell脚本将CSV文件上传到数据库

    Linux 薄荷 : using qt creator with qt4. 6.3

    linux - 如何从列表中删除除其他特定模式文件之外的某些模式文件?

    xml - Bash 将 XML 解析为数组

    linux - 如何使用 :arga in vim? 添加文件而不是子目录到 args 列表