简体   繁体   English

编写shell脚本来安装cron作业

[英]Writing a shell script to install cron job

This is the first time i am writing a shell script and i have very little information in the given timeline. 这是我第一次编写shell脚本,而且在给定的时间线中我的信息很少。 Though i am reading through different tutorials but i thought to ask what i want here as well. 虽然我正在阅读不同的教程,但我想在这里问我想要什么。

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. 我想编写一个shell脚本,在任何机器上编辑cronjob,添加一个每15分钟执行一次的新脚本。 so basically i have to add an entry 所以基本上我必须添加一个条目

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 它首先会更改cronSqlprocedure.sh的权限/执行权限
  • edit existing cron job and add this new entry into it. 编辑现有的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

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. 如果用户决定中断,清理临时文件, trap内容可确保最小的损坏。 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; 我通常在crontab命令上使用I / O重定向; you can perfectly well supply the file name as an argument. 你可以很好地提供文件名作为参数。

Note the escapes on \\$ORACLE_HOME and \\$PATH that William Pursell correctly pointed out should be present on \\$ORACLE_HOME and should (perhaps) be present on \\$PATH . 注意William Pursell正确指出的\\$ORACLE_HOME\\$PATH上的转义应该出现在\\$ORACLE_HOME并且应该(或许)出现在\\$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. 您需要决定是否要使用$PATHcron (完全最小的)值(在这种情况下,您需要反斜杠),或者是否要在cron脚本中使用用户当前的$PATH值。 Either could be correct - just be aware of which you choose and why. 两者都可能是正确的 - 只要知道你选择哪个以及为什么。 Remember, the environment provided by cron is always minimal; 请记住, cron提供的环境总是很少; you will get a setting for PATH, HOME, maybe TZ, probably USER and possibly LOGNAME; 您将获得PATH,HOME,也许是TZ的设置,可能是USER和可能的LOGNAME; that may be all. 这可能就是全部。 If you're not sure, try running a crontab entry which captures the environment in a file: 如果您不确定,请尝试运行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: 我会用:

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. { ... }将I / O重定向应用于所附的命令。 Note that there must be a semi-colon or newline before the } . 请注意, }之前必须有分号或换行符。

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; 我仍然认为trap不是太难,应该在任何创建临时文件的脚本中使用; however, it's your mess, not mine. 然而,这是你的烂摊子,不是我的。 I'm not convinced the $PWD is needed everywhere; 我不相信到处都需要$PWD ; I left it in one name and not in the other. 我把它留在一个名字而不是另一个名字。 If you don't supply a directory path, the $PWD is implied. 如果您不提供目录路径,则隐含$PWD 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. 只要名称是自洽的,就没有问题(使用变量有助于确保一致性),但要小心。

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 . 这将收集当前值并附加额外的行,将所有内容提供给脚本,该脚本在将结果反馈回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. 临时文件是100%可靠的 - 我会使用它,因为它不再复杂。 (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 } .) (我可以使用围绕所述第一对命令的括号;我可以使用周围的第二对命令的牙套,但我需要添加之间分号-)由取代} )。

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. 请注意,我的原始提案小心确保即使脚本多次运行,crontab文件中也只有一个条目用于该过程。 Your variants do not make sure of the idempotency. 您的变体无法确保幂等性。

Create a cron.d file 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 @Patrick from unix.stackexchange.com : 通过@Patrickunix.stackexchange.com答案:

I would recommend using /etc/cron.d over crontab . 我建议在crontab使用/etc/cron.d

You can place files in /etc/cron.d which behave like crontab entries. 您可以将文件放在/etc/cron.d ,其行为类似于crontab条目。 Though the format is slightly different. 虽然格式略有不同。

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(拉伸)上对我很有用。

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

I found a similar question: Edit crontab programmatically and force the daemon to refresh 我发现了一个类似的问题:以编程方式编辑crontab并强制守护进程刷新

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. 对于cronjob,你将基本上与crontab程序接口并提供它和全新的cron文件。 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. 您可以先检索已配置的cron作业,将其添加到列表中,然后再次调用crontab为其提供新的输入文件。

See the man-page for crontab for more information. 有关更多信息,请参阅crontab的手册页。

#!/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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM