无限循环 shell 脚本的内存使用情况

无限循环 shell 脚本的内存使用情况

因此,我有一个用于更新 MySQL 数据库的 shell 脚本,如下所示:

#!/bin/sh
mysql -h "localhost" -u "root" "-p********" "database" < "update.sql"
sleep 5
sh $0

它会休眠 5 秒钟,然后sh $0无限地重新运行脚本,无需我的干预。然而,我的问题是关于记忆的:

我对 shell 脚本比较陌生,但是内存是这样慢慢循环堆积的吗?远程服务器是否回收内存,或者脚本最终会到达截止点吗? (或者,它会因内存泄漏而崩溃吗?)

答案1

这不是循环,而是递归,并且内存随着时间线性增加,这是您不想要的。

如果你想要一个具有恒定内存使用量的循环,你可以这样做:

#!/bin/sh
while 1; do
  mysql -h "localhost" -u "root" "-p********" "database" < "update.sql"
  sleep 5
done

答案2

这取决于外壳。有些进行尾调用优化,有些则不进行。您可以通过运行轻松测试这一点SHELL -c 'ps $$'。如果ps看到自身,则 shell 已执行同一进程中的最后一个命令。如果ps看到 shell,则 shell 会运行子进程中的最后一个命令,就像处理非最后一个命令一样。

$ for s in dash bash mksh ksh zsh; do echo -n "$s "; $s -c 'ps -o comm= $$'; done 
dash dash
bash ps
mksh mksh
ksh ps
zsh ps

因此 bash、ksh 和 zsh 会进行尾调用优化,而 dash 和 mksh 则不会。

尾部调用优化只能针对脚本中的最后一个命令进行。例如,如果存在活动陷阱,则它不是尾部调用,因为 shell 需要留在后面以防陷阱被触发。

exec您可以通过将其放在命令前面来强制进行尾部调用。内置命令exec在同一进程中执行指定的命令。由于 shell 消失,脚本中的其他命令将不会被执行。

递归在 shell 脚本中并不惯用。使用循环会更惯用:

#!/bin/sh
while true; do
  mysql -h "localhost" -u "root" "-p********" "database" < "update.sql"
  sleep 5
done

或者,如果您希望脚本在命令sleep被信号终止时退出:

#!/bin/sh
while
  mysql -h "localhost" -u "root" "-p********" "database" < "update.sql"
  sleep 5
do
  :
done

或者,如果您希望脚本在mysql失败时退出:

#!/bin/sh
while
  mysql -h "localhost" -u "root" "-p********" "database" < "update.sql"
do
  sleep 5
done

相关内容