使用“while true”让脚本保持活力是个好主意吗?

Abh*_*jar 28 shell perl

我只是从另一个世界跳入 unix,想知道是否

while true
do
  /someperlscript.pl
done
Run Code Online (Sandbox Code Playgroud)

perl 脚本本身在内部有一个文件夹/文件观察器,当目标位置中的文件发生更改时会执行该观察器。

这是 ( while true) 一个好主意吗?如果不是,什么是首选的稳健方法?

TIA

编辑:由于这似乎引起了一些兴趣,这里是完整的场景。perl 脚本本身使用文件监视程序监视目录。收到新文件(它们通过 rsync 到达)后,它会选取新文件并进行处理。现在传入的文件可能已损坏(不要问..来自树莓派),有时进程可能无法处理它。我不知道确切的原因,因为我们还不知道所有的情况。

但是 - 如果进程由于某种原因确实失败了,我们希望它启动并运行并处理下一个文件,因为下一个文件与可能导致错误的前一个文件完全无关。

通常我会使用某种 catch all 并将整个代码包裹在它周围,以便它永远不会崩溃。但对 perl 不确定。

据我所知,使用 supervisord 之类的东西是一个很好的方法。

jll*_*gre 26

这取决于 perl 脚本返回的速度。如果它快速返回,您可能希望在执行之间插入一个小暂停以避免 CPU 负载,例如:

while true
do
  /someperlscript.pl
  sleep 1
done
Run Code Online (Sandbox Code Playgroud)

如果找不到脚本或立即崩溃,这也将防止 CPU 占用。

循环也可能更好地在 perl 脚本本身中实现以避免这些问题。

编辑:

由于您编写循环的唯一目的是在崩溃时重新启动 perl 脚本,更好的方法是将其实现为受监控的服务,但执行此操作的确切方法取决于操作系统。例如:Solaris smf、Linux systemd 或基于 cron 的重启程序。

  • 你可以做`while sleep 1; 做 ...` 来保存真正的调用。 (12认同)
  • @RaphaelAhrens 确实,尽管这会稍微改变初始行为。替代`直到!睡眠 1; 做 ...; done` 仍会在立即启动脚本时保存该内置调用。 (4认同)
  • 完全同意,如果您打算这样做,应该避免 **热循环**,并在循环内进行睡眠调用。也同意事件驱动的脚本(inotify 等)将是更好的解决方案。但是使用 while 循环本质上并不是邪恶的,除非它是无限的和热的。我认为更重要的问题可能是处理为什么 perl 脚本失败并需要重新启动的原因。 (4认同)
  • 更好:``sleep 1& /someperlscript.pl; 等等``. (2认同)
  • @jlliagre `直到!睡眠 1; 做 ...; done` *也* 不会立即启动脚本。这就像`while sleep 1; 做 ...; 完成`。像`while`,`until` 测试[在每次迭代之前](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_04_11)。(`until` 很少使用,所以如果某些实现不符合标准——尽管我怀疑任何 Bourne 风格的 shell 会以非标准方式对待 `until`——我测试了 `until ! sleep 5; do echo foo; done`在`bash`、`dash`、`busybox sh`、`ksh​​93`、`mksh`、`lksh`、`posh`、`zsh`和`yash`中,全部来自Ubuntu 16.04的存储库。) (2认同)
  • @EliahKagan 发现得很好。TBH,我从不使用 `until` 指令,我将它与 shell 中不存在的假设的 `do/until` 循环混淆。 (2认同)

Jac*_*all 14

关于 using 的其他答案inotify是正确的,但不是这个问题的答案。

进程管理器,例如supervisordupstart、 或runit,专为解决在服务崩溃时监视和重新启动服务的问题而设计。

您的发行版可能带有内置的流程主管。


Stu*_*aie 11

while true作为通用的“永远循环”结构很好。正如其他答案所说,循环的主体不应该是空的,或者由于循环内的命令不起作用而变成空的。

如果您使用的是 Linux,您可能需要使用类似 的命令inotifywait,这会使while循环更简单:

while inotifywait -qqe modify "$DIRECTORY"
do
    process_the_directory "$DIRECTORY"
done
Run Code Online (Sandbox Code Playgroud)

在这里,该inotifywait命令将等待文件系统事件发生(在本例中,当目录中的文件被写入时)。此时,它成功退出并执行循环体。然后它又回到等待状态。因为该inotifywait命令会等待目录中发生某些事情,所以它比不断轮询目录要高效得多。