【问题标题】:Writing a shell script to install cron job编写一个 shell 脚本来安装 cron 作业
【发布时间】:2012-02-23 09:41:30
【问题描述】:

这是我第一次编写 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

【问题讨论】:

  • 小心使用crontab -l - 某些版本的 crontab 会包含“请勿编辑此文件”之类的注释。您也许可以在这些平台上将您的 crontab 添加到 /etc/cron.d。
  • 您能否具体说明添加“请勿编辑此文件”限制的crontab -l 版本?这似乎毫无意义; crontab 命令的目的是允许您编辑文件中的条目。当然,您必须将已编辑的文件反馈回crontab,但是...

标签: linux bash shell cron


【解决方案1】:

对原始问题的简单回答

这一切似乎都是常规的 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 重定向;您可以很好地提供文件名作为参数。

注意\$ORACLE_HOME\$PATH 上正确指出的William Pursell 上的转义符应该出现在\$ORACLE_HOME 上,并且应该(也许)出现在\$PATH 上。您需要决定是要采用cron 提供的(完全最小的)值$PATH(在这种情况下您需要反斜杠)还是要在@ 中使用用户的当前值$PATH 987654332@ 脚本。任何一个都可能是正确的——只要知道你选择哪个以及为什么。请记住,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% 可靠的 - 我会使用它,因为它不再复杂。 (我可以在第一对命令周围使用括号;我可以在第二对命令周围使用大括号,但我需要在 -) 之间添加一个分号,由 @987654353 替换@.)

请注意,我最初的建议是谨慎地确保即使脚本运行多次,该进程的 crontab 文件中也只有一个条目。您的变体不能确保幂等性。

【讨论】:

  • 我不想让事情变得过于复杂,因为它只是为了测试目的。你能看看我的脚本吗
  • 小心 HEREDOC。除非您引用分隔符,否则 $ORACLE_HOME 将被扩展(可能为空字符串)。
  • 我没有足够的声誉来投票给你的答案..但是谢谢:)
  • 你的脚本帮助我解决了一个类似的问题,但是我确实稍微调整了你的代码,而不是写一个临时文件,我使用了一个子shell:crontab
【解决方案2】:

我发现了一个类似的问题:Edit crontab programmatically and force the daemon to refresh

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

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

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

【讨论】:

    【解决方案3】:
    #!/bin/sh SCRIPT=/home/personal/scripts/cronSqlprocedure.sh # 编写脚本。 猫 > $SCRIPT /dev/null;然后 VISUAL='sed -i -e "\$a\ 0,15,30,45 * * * * '$SCRIPT'"' crontab -e 菲

    【讨论】:

    • 前半部分与我的答案几乎相同;我同意这一点。不过,这似乎是一种扭曲的方式来更新 crontab 条目。
    • @Jonathan leffler 这绝对是歪曲的。我没有意识到您可以简单地回显到 crontab。这样干净多了!
    【解决方案4】:

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

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

    @Patrick 来自 unix.stackexchange.com 的回答:

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

    您可以将文件放在/etc/cron.d 中,其行为类似于 crontab 条目。虽然格式略有不同。

    Patrick 指出它可能不适用于所有系统,但他的回答既被接受又获得最多票数。它适用于我在 debian 9 (stretch) 上。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-03
      • 2016-11-07
      • 1970-01-01
      • 1970-01-01
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多