在某些系统上,某些命令(例如
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 上运行。
请注意,如果 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% 确定)。否则,通过绝对路径获取它。