Linux 脚本:通过 Crontab 将内存打印保存到文本文件中始终为空白

Linux Script: Saving Memory print into text file via Crontab always blank

在我的 CentOS 中,我试图将 CPU USAGE 和 FREE MEMORY 输出数字打印到文本文件中。但是当我在终端输入时,一切都很好。但是当它通过 crontab 执行时,MEMORY 输出总是空白。

在终端中手动输入:

# echo CPU: `top -b -n1 | grep "Cpu(s)" | awk '{print  + }'`, RAM: `awk '/^Mem/ {print }' <(free -m)` >> ~/stats.txt
# cat ~/stats.txt
CPU: 3.8, RAM: 1307

Crontab 中的相同命令:

*/10 * * * * echo CPU: `top -b -n1 | grep "Cpu(s)" | awk '{print  + }'`, RAM: `awk '/^Mem/ {print }' <(free -m)` >> ~/stats.txt

然后在文本文件中:

# cat ~/stats.txt
CPU: 3.4, RAM: 
CPU: 4.1, RAM: 
CPU: 3.9, RAM: 

为什么 RAM 输出总是空白?

您正在命令中使用进程替换:

<(free -m)

。这是标准 POSIX shell 中不存在的 Bash 功能,甚至在某些平台上的 Bash 中也不存在。

除非您通过在 crontab 中设置 SHELL 变量来指定,否则 cron 通过 /bin/sh 运行您的命令。以这种方式开始时,bash 会在大多数方面尽力模仿 POSIX shell。这包括拒绝承认流程替代。在我现在的系统上,例如:

$ /bin/bash -c "awk '/^Mem/ {print $4}' <(free -m)"
11603

但是

$ /bin/sh -c "awk '/^Mem/ {print $4}' <(free -m)"
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `awk '/^Mem/ {print }' <(free -m)'

由于您的命令(大概)产生了错误,可能是 cron 向您发送了有关该错误的电子邮件。

您可以在您的 crontab 中设置 SHELL=/bin/bash,但我不明白您为什么首先需要进程替换。如果您不指定文件名,awk 将从标准输入读取,因此您可以轻松地将 free 的输出传输到其中。

$ /bin/sh -c "free -m | awk '/^Mem/ {print $4}'"
11612

对应的 crontab 行是

*/10 * * * * echo CPU: `top -b -n1 | grep "Cpu(s)" | awk '{print  + }'`, RAM: `free -m | awk '/^Mem/ {print }'` >> ~/stats.txt

这更标准,(对我而言)更容易阅读,并且内部更一致。