Linux 编写一个 shell 脚本来安装 cron 作业
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9083467/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Writing a shell script to install cron job
提问by Em Ae
This is the first time i am writing a shell script and i have very little information in the given timeline. Though i am reading through different tutorials but i thought to ask what i want here as well.
这是我第一次编写 shell 脚本,在给定的时间线中我的信息很少。虽然我正在阅读不同的教程,但我也想在这里问我想要什么。
I want to write a shell script, which on any machine, edit the cronjob, add a new script to be executed at every 15 minutes. so basically i have to add an entry
我想编写一个 shell 脚本,在任何机器上,编辑 cronjob,添加一个每 15 分钟执行一次的新脚本。所以基本上我必须添加一个条目
0,15,30,45 * * * * /home/personal/scripts/cronSqlprocedure.sh
0,15,30,45 * * * * /home/personal/scripts/cronSqlprocedure.sh
What i want in the shell script
我在shell脚本中想要什么
- it would first change the permissions/execution rights for
cronSqlprocedure.sh
- editexisting cron job and add this new entry into it.
- 它将首先更改权限/执行权限
cronSqlprocedure.sh
- 编辑现有的 cron 作业并将这个新条目添加到其中。
If possible, I would like to write cronSqlprocedure through the shell script too, since it requires couple of variables which may varry from system to system.
如果可能,我也想通过 shell 脚本编写 cronSqlprocedure,因为它需要几个变量,这些变量可能因系统而异。
export ORACLE_HOME=/opt/app/oracle/product/11.2.0/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH
export ORACLE_SID=HEER
These lines have to be configured for each machine in the cronSqlprocedure.sh
.
必须为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
采纳答案by Jonathan Leffler
Simple Answer to Original Question
对原始问题的简单回答
It all seems like routine shell scripting:
这一切似乎都是常规的 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
The trap
stuff ensures minimum damage if the user decides to interrupt, cleaning up the temporary file. Note that the old version of the script, if any, has already been clobbered. If you wanted to, you could arrange to create the script into another temp file, and only finish the moving when your satisfied. I typically use I/O redirection on the crontab
command; you can perfectly well supply the file name as an argument.
trap
如果用户决定中断,清理临时文件,这些东西可以确保最小的损害。请注意,旧版本的脚本(如果有)已经被破坏。如果您愿意,您可以安排将脚本创建到另一个临时文件中,并在您满意时完成移动。我通常在crontab
命令上使用 I/O 重定向;您完全可以提供文件名作为参数。
Note the escapes on \$ORACLE_HOME
and \$PATH
that William Pursellcorrectly pointed out should be present on \$ORACLE_HOME
and should (perhaps) be present on \$PATH
. You need to decide whether you want to take the cron
-provided (totally minimal) value of $PATH
(in which case you want the backslash) or whether you want to use the user's current value of $PATH
in the cron
script. Either could be correct - just be aware of which you choose and why. Remember, the environment provided by cron
is always minimal; you will get a setting for PATH, HOME, maybe TZ, probably USER and possibly LOGNAME; that may be all. If you're not sure, try running a crontab entry which captures the environment in a file:
需要注意的逃逸\$ORACLE_HOME
和\$PATH
那个威廉Pursell正确地指出,应该出现在\$ORACLE_HOME
和应(也许)存在的\$PATH
。您需要决定是要采用cron
-provided (完全最小)的值$PATH
(在这种情况下您需要反斜杠)还是要$PATH
在cron
脚本中使用用户的当前值。两者都可能是正确的 - 只需注意您选择哪个以及为什么。请记住,由提供的环境cron
总是最小的;您将获得 PATH、HOME、TZ、USER 和 LOGNAME 的设置;这可能就是全部。如果您不确定,请尝试运行一个 crontab 条目来捕获文件中的环境:
* * * * * env > /tmp/cron.env
You're likely to find that the file is small. Don't forget to remove the entry after testing it.
您可能会发现该文件很小。测试后不要忘记删除该条目。
One good thing that you're to be commended for:
值得称赞的一件好事:
- Your script (a) ensures that it sets the environment, and (b) runs a simple command from the
crontab
entry, leaving the script to do the hard work.
- 您的脚本 (a) 确保它设置环境,并且 (b) 从
crontab
条目运行一个简单的命令,让脚本完成繁重的工作。
In my view, the entries in the crontab
file should indeed be simple like that, invoking a purpose-built script to do the real work.
在我看来,crontab
文件中的条目确实应该像这样简单,调用一个专门构建的脚本来完成真正的工作。
Critique of Proposed Script in the Revised Question
对修订问题中拟议脚本的批评
#!/bin/bash
ORACLE_HOME="/opt/app/oracle/product/11.2.0/dbhome_1"
ORACLE_SID="HEER"
ORACLE_USER="USER1"
ORACLE_PASSWORD="USERPASS"
Thus far, no problem:
到目前为止,没有问题:
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 is horribly repetitive, and starting out with append is not good. I would use:
这是可怕的重复,从 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
The { ... }
apply the I/O redirection to the enclosed commands. Note that there must be a semi-colon or newline before the }
.
该{ ... }
应用I / O重定向到封闭的命令。请注意, . 之前必须有一个分号或换行符}
。
chmod 755 $PWD/sqlcronprocedure.sh
Since I have a variable for the file name, I'd use it:
由于我有一个文件名变量,我会使用它:
chmod 755 $cronscript
Then we have a problem with repetition here, plus not cleaning up behind ourselves:
那么我们这里有重复的问题,再加上自己没有清理干净:
crontab -l > $PWD/sqlcorn.sh
echo "0,15,30,45 * * * * $PWD/sqlcronprocedure.sh" >> $PWD/sqlcorn.sh
crontab $PWD/sqlcorn.sh
Thus I'd write:
因此我会写:
crontab=sqlcron.sh
crontab -l > $crontab
echo "0,15,30,45 * * * * $cronscript" >> $crontab
crontab $crontab
rm -f $crontab
I still think that trap
is not too hard and should be used in any script that creates temporary files; however, it's your mess, not mine. I'm not convinced the $PWD
is needed everywhere; I left it in one name and not in the other. If you don't supply a directory path, the $PWD
is implied. I also note that you're using a slightly different script name in your proposed full script from the one in the original. As long as the names are self-consistent, there isn't a problem (and using a variable helps ensure consistency), but be careful.
我仍然认为这trap
并不太难,应该在任何创建临时文件的脚本中使用;然而,这是你的烂摊子,不是我的。我不相信$PWD
到处都需要它;我把它留在一个名字而不是另一个名字。如果您不提供目录路径,则$PWD
是隐含的。我还注意到,您在提议的完整脚本中使用了与原始脚本略有不同的脚本名称。只要名称是自洽的,就没有问题(并且使用变量有助于确保一致性),但要小心。
I'm not sure that I'd actually do it this way, but you could also avoid the temporary file using:
我不确定我是否真的会这样做,但您也可以使用以下方法避免临时文件:
{
crontab -l
echo "0,15,30,45 * * * * $cronscript"
} | (sleep 1; crontab -)
This collects the current value and appends the extra line, feeding all that into a script that sleeps for a second (to allow the first part time to complete) before feeding the results back into crontab
. There's a question of how reliable is the one second delay, mainly. It's likely fine, but not guaranteed. The temporary file is 100% reliable - I'd use it because it isn't any more complex. (I could use parentheses around the first pair of commands; I could use braces around the second pair of commands, but I'd need to add a semi-colon between the -
and the )
that is replaced by }
.)
这将收集当前值并附加额外的行,将所有这些输入到一个休眠一秒钟的脚本中(以允许第一部分时间完成),然后将结果返回到crontab
. 主要是一秒延迟的可靠性问题。可能没问题,但不能保证。临时文件 100% 可靠 - 我会使用它,因为它并不复杂。(我可以在第一对命令周围使用括号;我可以在第二对命令周围使用大括号,但我需要在 the-
和 the之间添加一个分号,)
由}
.)
Note that my original proposal was careful to ensure that even if the script was run multiple times, there'd be only one entry in the crontab file for the process. Your variants do not make sure of the idempotency.
请注意,我最初的提议很小心,以确保即使脚本多次运行,在 crontab 文件中也只有一个条目用于该进程。您的变体不能确保幂等性。
回答by Mr. Shickadance
I found a similar question: Edit crontab programmatically and force the daemon to refresh
我发现了一个类似的问题:Edit crontab programmatically and force the daemon to refresh
Changing the permissions of the file is typical shell scripting with many resources available.
更改文件的权限是具有许多可用资源的典型 shell 脚本。
For the cronjob, you'll want to essentially interface with the crontab program and feed it and entirely new cron file. You can first retrieve already configured cron jobs, add yours to the list, and then call crontab again to give it the new input file.
对于 cronjob,您需要本质上与 crontab 程序交互并提供它和全新的 cron 文件。您可以首先检索已配置的 cron 作业,将您的作业添加到列表中,然后再次调用 crontab 为其提供新的输入文件。
See the man-page for crontabfor more information.
有关更多信息,请参阅crontab的手册页。
回答by William Pursell
#!/bin/sh SCRIPT=/home/personal/scripts/cronSqlprocedure.sh # write the script. cat > $SCRIPT << 'EOF' export ORACLE_HOME=/opt/app/oracle/product/11.2.0/dbhome_1 export PATH=$ORACLE_HOME/bin:$PATH export ORACLE_SID=HEER EOF # Make the script executable chmod +x $SCRIPT # Add this script to the existing crontab. This relies on your # sed supporting -i. if it does not, it is probably easiest to # write a simple script that does the edit and set VISUAL to that script if ! crontab -l | grep $SCRIPT > /dev/null; then VISUAL='sed -i -e "$a\ 0,15,30,45 * * * * '$SCRIPT'"' crontab -e fi
回答by Jonathan
Create a cron.dfile such as /etc/cron.d/my-sql-proc
创建一个cron.d文件,例如/etc/cron.d/my-sql-proc
0,15,30,45 * * * * root /home/personal/scripts/cronSqlprocedure.sh
#
# run-as user
Answer by @Patrickfrom unix.stackexchange.com:
通过回答@Patrick从unix.stackexchange.com:
I would recommend using
/etc/cron.d
overcrontab
.You can place files in
/etc/cron.d
which behave like crontab entries. Though the format is slightly different.
我建议使用
/etc/cron.d
overcrontab
。您可以放置
/etc/cron.d
行为类似于 crontab 条目的文件。虽然格式略有不同。
Patrick points out it may not work on all systems, but his answer is both accepted and has the most votes. It works well for me on debian 9 (stretch).
帕特里克指出它可能不适用于所有系统,但他的答案既被接受又获得了最多的选票。它在 debian 9 (stretch) 上对我来说效果很好。
source:https://unix.stackexchange.com/questions/117244/installing-crontab-using-bash-script#117254
来源:https : //unix.stackexchange.com/questions/117244/installing-crontab-using-bash-script#117254