在我的/etc/crontab
Linux文件中定义了以下cronjob:
* * * * * oracle cd "/home/oracle" && exp "user"/"password"@"TNS" owner="user" file="user".dmp log="user".log;
为了举例说明,在所有字段中都使用星号*
来表示exp
命令执行的任何时间。
当我尝试通过CLI直接执行这个命令时,它工作得非常好,也就是说,在执行命令的目录下创建了备份和日志文件:
cd "/home/oracle" && exp "user"/"password"@"TNS" owner="user" file="user".dmp log="user".log
然而,由于某些原因,当cron试图执行它时,它不起作用。为什么?我已经尝试在文件的顶部定义PATH
和SHELL
变量,以便cron环境可以看到在哪里可以找到这个exp
可执行文件。就像这样:
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$ORACLE_HOME/bin
* * * * * oracle cd "/home/oracle" && exp "user"/"password"@"TNS" owner="user" file="user".dmp log="user".log;
我试图将$ORACLE_HOME替换为它的文字目录,也就是/opt/oracle
;
我要么尝试根据其绝对路径替换exp
命令到它所在的位置,就像这样:/opt/oracle/bin/exp
;
Cron可以正常工作,因为当我执行一个更简单的任务时(例如,在cd命令将Cron带入的目录中创建一个文件),它可以正常工作。
* * * * * cd "/home/oracle" && touch text.txt;
为什么会发生这种情况?我是否错过了一些关于cron如何工作的相关信息?
编写shell脚本来执行导出。在脚本中定义环境变量;您不能在crontab中这样做。测试您的shell脚本独立工作,然后使用cron运行shell脚本。
/home/oracle/export.sh:
#!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$ORACLE_HOME/bin
export PATH
/opt/oracle/bin/exp user/password@TNS owner=user file=/home/oracle/user.dmp log=user.log;
crontab:
* * * * * /home/oracle/export.sh
也: - 也许不要每分钟运行一次作业,除非这是你真正想要做的…
- 考虑使用Datapump (expdp)而不是export,除非你有非常具体的理由使用exp。
- 考虑而不是将用户名/密码放在脚本中。您可以使用带有OS认证的帐户,或者使用Oracle Wallet来保存您的凭据:https://pmdba.wordpress.com/2020/01/13/how-to-hide-oracle-passwords-in-a-script/
由cron提交的进程不会执行.bash_profile脚本,就像登录到命令行shell进程(如ssh)时一样。因此,您的cron作业不会继承命令行进程所拥有的所有环境。
与其试图在crontab条目中将一堆命令堆叠到一个"命令行"上,不如编写一个shell脚本来完成您想要/需要的一切—包括调用oraenv来设置环境:
脚本my_expdp.sh#!/bin/sh
ORAENV_ASK=NO
ORACLE_SID=$1
source oraenv
expdp user/pswd owner=scott file=scott.dmp log=scott.log
然后,在crontab
中* * * * * /home/oracle/my_expdp.sh mydb
——编辑我看到@pmdba发布的解决方案与我发布的基本相同,即使我正在写我的答案。
——编辑修改以允许对多个数据库使用单个脚本。在脚本中,不要硬编码ORACLE_SID的值,而是将其设置为调用脚本时设置的第一个命令行参数的值。然后,在crontab条目(无论如何必须为每个作业硬编码)上设置ORACLE_SID的值。在上面的例子中,ORACLE_SID将被设置为'mydb'。