具有多个命令和可重入的 BASH 变量

Posted

技术标签:

【中文标题】具有多个命令和可重入的 BASH 变量【英文标题】:BASH Variables with multiple commands and reentrant 【发布时间】:2010-11-10 09:47:52 【问题描述】:

我有一个从另一个文件获取内容的 bash 脚本。另一个文件的内容是我想执行并比较返回值的命令。一些命令有多个命令,由分号 (;) 或与号 (&&) 分隔,我似乎无法完成这项工作。为此,我创建了一些测试脚本,如下所示:

test.conf 是测试源文件

Example-1(这个可行),我的输出相差 2 秒

test.conf

CMD[1]="日期"

test.sh

.测试.conf 我=2 回声“$($CMD[$i])” 睡觉 2 回声“$($CMD[$i])”

示例 2(这不起作用) test.conf(与上面相同的脚本)

CMD[1]="日期;日期"

Example-3(试过这个,它也不起作用) test.conf(与上面相同的脚本)

CMD[1]="日期 && 日期"

我不希望我的变量 CMD 位于刻度线内,因为那样的话,命令将在调用源时执行,而且我看不到重新评估变量的方法。

这个脚本本质上是在 pass-1 上调用 CMD 来检查某些东西,如果在 pass-1 上我得到一个错误的读数,我会在脚本中做一些工作来纠正错误的读数并重新执行和重新评估输出指令;第 2 次。

这是一个例子。在这里,我正在检查 SSHD 是否正在运行。如果我在 pass-1 上评估 CMD[1] 时它没有运行,我将启动它并重新评估 CMD[1]。

test.conf

CMD[1]=`pgrep -u root -d , sshd 1>/dev/null;回声$?`

所以如果我为我的测试脚本修改这个,那么 test.conf 变成: 注意:刻度线没有显示,但它是我键盘上 ~ 标记下方的键。

CMD[1]=`date;date` 或 `date && date`

我的脚本看起来像这样(处理刻度线)

.测试.conf 我=2 回声“$CMD[$i]” 睡觉 2 回声“$CMD[$i]”

尽管延迟了 2 秒,但我还是打印了两次相同的日期/时间。因此,CMD 没有得到重新评估。

【问题讨论】:

您的问题不清楚 - 实际上,我没有看到问题。你到底想做什么,哪里出了问题?您的“示例”、“test.conf CMD[1]=pgrep -u”... 没有什么意义——“源文件”在哪里?你是如何解析参数的——我看到的你缺少引号? 这是一个测试脚本,不是实际的。因此 $i 仍然存在的原因(cut -n- past)并且缺乏清晰度。 CMD[x] 其中 x = 0 ... 10 是返回 1 或 0 的测试条件;主要是进程是否运行,类似于上面给出的 pgrep 示例。除了 CMD,我还调用了相应的 RESTART[x],在调用它之后,我重新评估 CMD[x] 以查看进程是否重新启动。在其他示例中,我正在检查是否存在日志文件。我不想用这些细节让论坛无聊,但它可能会有所帮助。谢谢! 【参考方案1】:

首先,你不应该使用反引号,除非你需要兼容不支持$()的旧shell - 只有这样

其次,我不明白您为什么要设置 CMD[1],然后调用 CMD[$i] 并将 i 设置为 2

无论如何,这是一种方式(它类似于巴里的部分答案):

CMD[1]='$(date;date)'    # no backticks (remember - they carry Lime disease)
eval echo "$CMD[1]"    # or $i instead of 1

【讨论】:

这也有效。我没有想到这个方法。太好了,谢谢!【参考方案2】:

从你的问题的几行来看,我本来希望有这样的方法:

#!/bin/bash

while read -r line; do
    # munge $line
    if eval "$line"; then
        # success
    else
        # fail
    fi
done

如果您在源代码中有反引号,则必须避开它们以避免过早评估它们。此外,反引号并不是评估代码的唯一方法 - 如上所示,还有 eval。也许你要找的是eval

例如,这一行:

CMD[1]=`pgrep -u root -d , sshd 1>/dev/null; echo $?`

应该看起来更像这样:

CMD[1]='`pgrep -u root -d , sshd 1>/dev/null; echo $?`'

【讨论】:

这行得通!但是,根据我和您之前的 cmets(我们同意),我不想在那里出现倒勾。此脚本不会在 Linux 以外的任何其他环境中运行,我无法控制 BASH,并且同意您的可移植性问题!

以上是关于具有多个命令和可重入的 BASH 变量的主要内容,如果未能解决你的问题,请参考以下文章

可重入函数的问题解答

可重入函数与不可重入函数

可重入概念

线程安全与可重入

内核轻探,锁,虚拟地址空间

ReentrantLock实现原理及源码分析