unix ksh超时条件执行

daolsyd0  于 2023-11-18  发布在  Unix
关注(0)|答案(2)|浏览(135)

在某些系统上,某些命令(如dfprtdiag)(仅限Sun)可以由于各种原因无限期地挂起。我正在尝试加强我的ksh脚本,以便它们遇到这些挂起时,它们会失败而不是无限期地停止。为此,我计划使用timeout命令,但它并不是100%的内存都可用,所以我必须有条件地使用timeout *,只有当它存在 * 时,如果没有的话,我想找一个紧凑的命令-因为我需要将其插入到大量现有的命令链中,而复杂性的增加最小。
对于大多数命令来说,这很简单。但是timeout * 在超时 *(124,143或271)时返回非零状态码,而不仅仅是因为它不存在而无法运行时(1或127)。因此,简单的||操作符无法区分“没有这样的命令”和“操作超时”。因此,这将不起作用:

(timeout 5 df || df) # will execute bare df if there is no timeout *or* if the first df times out, thus hanging

字符串
另一个测试timeout命令而不尝试执行它的选项也因为同样的原因不起作用。超时条件下的timeout本身在||上看起来就像timeout命令不存在一样:

(command -v timeout >/dev/null && timeout 5 df || df) # same result


我需要一个紧凑的 if-then-else 返回代码,其中最后一段(else)的返回代码仅由第一段(if)驱动,而不受中间一段(then)的影响。如果timeout命令存在,则使用它,否则,执行bare命令。我不希望超时条件导致执行bare命令。
这里有一种正确的方法,通过测试两次:

(command -v timeout >/dev/null || df; command -v timeout >/dev/null && timeout 5 df)


但这感觉并不优雅;我不得不重复command -v timeout >/dev/null两次。另一个只适用于一个测试的选项:

(command -v timeout >/dev/null; if [ $? -eq 0 ]; then timeout 5 df; else df; fi)


但是,明确的 if-then-else-fi 与分号等感觉沉重,而不是紧凑,因为它应该。
有没有更简洁、更紧凑的方法来实现这一点?它需要在AIX、Sun、HP-UX和Linux上运行旧的ksh88

zte4gxcn

zte4gxcn1#

请注意,如果AB失败,A && B || C将执行C。您需要使用if正确分离B和C。
听起来你想创建一个函数,而且很可能是在一个库文件中:如果这是在文件my_timeout.ksh中,

timeout() {
  if command -v timeout >/dev/null; then
    command timeout "$@"
    # possibly capture $? and add a case statement 
    # if you need to do special things upon actual timeout
  else
    "$@"
  fi
}

字符串
然后在你的脚本中,最小的变化是:

. my_timeout.ksh
timeout df --with args


ksh .将在PATH中查找要源的文件(至少在ksh93中,而不是100%确定ksh88)。否则,通过绝对路径来源。

a6b3iqyw

a6b3iqyw2#

创建一个目录timeout,然后:

  • 把它放在$PATH中,在开始的地方(在/bin//usr/bin之前)
  • 在该目录中创建脚本,例如df
#!/bin/bash

timeout 5 /usr/bin/df "$@"

字符串
(显然只适用于您希望有超时的命令)

相关问题