crontab中引入环境变量

概述

crontab 中默认使用的环境变量有限,导致定时任务中执行的脚本,会找不到命令。在执行的脚本中导入当前用户的环境变量可以解决问题。

添加方式

脚本中添加环境变量的方式如下:

1
2
. /etc/profile
~/.bash_profile

我这里使用了第一种。
crontab 中默认使用的环境变量如下:

1
/usr/bin:/bin

脚本中添加用户环境变量后,变为:

1
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

2>&1使用

排查问题的过程中使用了2>&1,很关键。问题现象是,route > log.txt手动执行后,文件有内容,放到定时任务中只生成文件但是没有内容。
直到加入了2>&1才看到错误信息:找不到route命令,进而想到是环境变量的问题。这部分内容转自 https://www.cnblogs.com/yangyongzhi/p/3364939.html

相关知识

  1. 默认地,标准的输入为键盘,但是也可以来自文件或管道(pipe |)。
  2. 默认地,标准的输出为终端(terminal),但是也可以重定向到文件,管道或后引号(backquotes `)。
  3. 默认地,标准的错误输出到终端,但是也可以重定向到文件。
  4. 标准的输入,输出和错误输出分别表示为STDINSTDOUTSTDERR,也可以用0,1,2来表示。
  5. 其实除了以上常用的3中文件描述符,还有3~9也可以作为文件描述符。3~9你可以认为是执行某个地方的文件描述符,常被用来作为临时的中间描述符。
  6. 实例:
1
2
3
4
5
6
command 2>errfile # command的错误重定向到文件errfile。
command 2>&1 | ... # command的错误重定向到标准输出,错误和标准输出都通过管道传给下个命令。
var=`command 2>&1` # command的错误重定向到标准输出,错误和标准输出都赋值给var。
command 3>&2 2>&1 1>&3 | ... # 实现标准输出和错误输出的交换。
var=`command 3>&2 2>&1 1>&3` # 实现标准输出和错误输出的交换。
command 2>&1 1>&2 | ... (wrong...) # 这个不能实现标准输出和错误输出的交换。因为shell从左到右执行命令,当执行完2>&1后,错误输出已经和标准输出一样的,再执行 1>&2也没有意义。

“2>&1 file”和 “> file 2>&1”区别

1
2
cat food 2>&1 >file #错误输出到终端,标准输出被重定向到文件file。
2)cat food >file 2>&1 #标准输出被重定向到文件 file,然后错误输出也重定向到和标准输出一样,所以也错误输出到文件file。

注意

通常打开的文件在进程推出的时候自动的关闭,但是更好的办法是当你使用完以后立即关闭。用m<&-来关闭输入文件描述符m,用m>&-来关闭输出文件描述符m。如果你需要关闭标准输入用<&->&-被用来关闭标准输出。

同时输出到终端和文件

1
copy source dest | tee.exe copyerror.txt

参考

  1. http://docstore.mik.ua/orelly/unix/upt/ch45_21.htm
  2. http://www.unix.com/shell-programming-scripting/34011-meaning-dev-null-2-1-a.html
  3. http://docstore.mik.ua/orelly/unix/upt/ch08_13.htm

脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/sh
. /etc/profile
DATE=$(date "+%F %X")
gateway="192.168.0.1"
log="/home/root/chkroute.log"
txt="/home/root/route.txt"
route > $txt 2>&1

awk -v varDATE="$DATE" -v vargateway="$gateway" -v varlog="$log" -v vartxt="$txt" '{
if($1 == "default")
{
if($2 != vargateway)
{
printf("[%s]gateway %s is error, now del and add %s!\n", varDATE, $2, vargateway) >> varlog
cmd="route del default gw "$2
system(cmd);
system("sleep 1")
cmd="route add default gw "vargateway
system(cmd);
};
}
}' "$txt"