我正在尝试将以下命令添加到 crontab:
I=1; for X in $(/bin/ls -r /var/tmp/*); do [ $((I++)) -le 28 ] && echo "lower" || echo "higher"; done
当在命令行(在 bash 中)执行时,该命令工作正常。但是当我将该行添加到 crontab 并执行时,cron 会抱怨:
/bin/sh: 1: arithmetic expression: expecting primary: "I++"
我需要在 cron 中使用不同的语法吗?
编辑1:我已经 替换sh
为bash
:/etc/crontab
SHELL=/bin/bash
我已经重新启动cron
,但下面的 cron 行仍然没有执行:
(I=1; for X in $(/bin/ls -r /var/tmp/*); do [ $((I++)) -le 28 ] && echo "lower" || echo "higher"; done)
该错误表明,它仍然被解释为/bin/sh
而不是/bin/bash
:
/bin/sh: 1: arithmetic expression: expecting primary: "I++"
答案1
Cron,如果我没记错的话,默认为/bin/sh
.检查/etc/crontab/
线路SHELL=
。很可能设置为/bin/sh
( dash
)。我相信你可以SHELL=/bin/bash
在你自己的用户crontab文件(由编辑的crontab -e
)中设置。或者您可以编写脚本。
答案2
是的,您需要使用sh
语法。您可以找到可移植标准sh
语法的规范那里。
在这种情况下,您想要[ "$((i+=1))" -le 29 ]
,或者如果您sh
基于旧版本,ash
该版本尚不支持全套标准算术运算符,请使用[ "$i" -le 28 ] ...; i=$(($i + 1))
。
警告:/var/tmp
在 cron 下处理一个世界可写目录就像打开一罐蠕虫病毒一样安全。
您必须将文件名及其类型视为不可信且极其肮脏的。
你的$(/bin/ls -r /var/tmp/*)
特别是假的,因为它对文件名可能包含哪些字符做了很多假设,并假设它们都不是目录或目录的符号链接。
答案3
为了使其完全可移植,您可以将 $() 语法替换为:
I=1; for X in `/bin/ls -r /var/tmp/*`; do [ $I -le 28 ] && echo "lower" || echo "higher"; I=`expr $I + 1`; done
但要小心 cron 作业和全局可写目录。