因此,我有一个用于更新 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