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
这更标准,(对我而言)更容易阅读,并且内部更一致。
在我的 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
这更标准,(对我而言)更容易阅读,并且内部更一致。