ksh 条件执行超时

问题描述 投票:0回答:1

在某些系统上,某些命令(例如

df
prtdiag
(仅限 Sun))可能会由于各种原因无限期挂起。我正在尝试强化我的
ksh
脚本,以便它们在遇到问题时会失败,而不是无限期地停滞。为此,我计划使用
timeout
命令,但它并不是在 100% 的足迹上普遍可用,因此我必须有条件地使用
timeout
(仅当它存在时),并且裸命令 if事实并非如此。我想为此找到一个compactone-liner,因为我需要将其插入到众多现有的命令链中,同时尽量减少复杂性的增加。

对于大多数命令来说,这很简单。但是

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

出于同样的原因,测试超时命令而不尝试执行它的另一个选项也不起作用。超时条件下的超时本身看起来

||
就像超时命令不存在一样:

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

我需要一个紧凑的 if-then-else 作为返回码,其中最后一段(else)的返回码仅由第一段(if)驱动,而不受中间段(then)的影响)。如果

timeout
命令存在,则使用它,否则,执行裸命令。我确实想要超时条件来导致执行裸命令。

这是一种正确工作的方法,通过测试两次:

(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 之类的感觉很笨拙,并且没有应有的紧凑。

对于更干净、更紧凑的方法有什么建议吗?它需要在

ksh88
之前的 AIX、Sun、HP-UX 和 Linux 上运行。

shell unix ksh
1个回答
0
投票

请注意,如果 A

B 失败,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 中,对于 ksh88 不是 100% 确定)。否则,通过绝对路径获取它。

© www.soinside.com 2019 - 2024. All rights reserved.