Bash在循环中设置一个全局变量并保留其值 - 或者为假人处理替代

Has*_*yed 7 bash scripting posix process-substitution

我是一名C/C++程序员,一般来说非常愚蠢(至少bash做的事情让我感到困惑).我无法解决流程替代问题.

我需要定义一个全局布尔值,将它设置在循环中的某个位置,并在全局范围内使用它.有人可以用最简单的方式解释如何调整下面的代码,让我实现我的用例,简单到足以使我明天不再扭曲我的大脑来尝试掌握过程替换.

# DEFINE HERE

for i in `seq 0 ${DAEMON_COUNT}`;
do
        if [ ! -d "data$i" ]; then
# SET HERE
                echo "data$i does not exist. Creating...";
                mkdir data$i
        fi
done

# TEST AND USE HERE
Run Code Online (Sandbox Code Playgroud)

说实话,我不认为bash能胜任这个任务......下一个块看起来像这样.

echo "-------------------------------------------------------------------------------"
echo "checking the state of potentially running daemons"
for i in `seq 0 ${DAEMON_COUNT}`;
do
        if [ ! -e "data$i/mongod.lock" ] ; then
                echo "[no lock file] mongod process $i does not exist"
        else
                echo "[lock file exists] process $i lock file exists "
                I_PID=`cat data$i/mongod.lock`

                if [ ! ${I_PID} ]; then
                        echo "    [GOOD] lock pid empty"
                elif [ "`ps -p ${I_PID} | grep ${I_PID}`" ]; then
                        echo "    [GOOD] data1 pid: ${I_PID} running"
                else 
                        echo "[PROBABLY FATAL] data1 pid: ${I_PID} not running."
                fi 
        fi
done
echo "-------------------------------------------------------------------------------"
Run Code Online (Sandbox Code Playgroud)

我现在需要的是一个全局结构数组,以便我可以遍历它们并采取条件操作来正确初始化我的守护进程:/.

可能只是使用libc并在lua中执行此操作,我拒绝的唯一原因是必须安装岩石,我不喜欢临时代码存储库呕吐他们想要的任何东西到我的机器上:D

Ada*_*man 9

要理解的重要一点是:子进程诞生时有自己的环境,不能影响其父进程的变量.如果在子进程中设置变量,则不会影响父进程中变量的值.这些实际上是两个不同的变量,恰好具有相同的名称.

要理解的第二件事是bash将命令作为子进程运行.有两个与此问题相关的案例:

  1. 通过管道连接的每个进程|都是当前shell的子进程.
  2. 使用重定向(例如<)运行单个内置命令不会产生子进程.

这是一个简单的会话,演示了这些想法:

$ somevar=initial
$ echo test1 | read somevar
$ echo $somevar
initial
$ read somevar < <(echo test2)
$ echo $somevar
test2
Run Code Online (Sandbox Code Playgroud)

第一个read是子进程,因此somevar在主shell中不会改变.第二个read是由主shell本身执行的,因此somevar会更新.

这意味着您的代码将按预期工作,除非您在for循环之前或之后添加管道,即这可以按照您的要求运行:

# DEFINE HERE
SOMEVAR=0
DAEMON_COUNT=10

for i in `seq 0 ${DAEMON_COUNT}`;
do
        if [ ! -d "data$i" ]; then
# SET HERE
                SOMEVAR=10
                echo "data$i does not exist. Creating...";
                mkdir data$i
        fi
done

# TEST AND USE HERE
echo ${SOMEVAR}     # This displays 10
Run Code Online (Sandbox Code Playgroud)

  • @HassanSyed,只要你没有使用`local`关键字为你的变量添加前缀,那么写成as-is*的代码应该像Adam所说的那样工作.大多数情况下,当人们执行`some_command |时会发生此问题 读线; 做someVar = foo; 完成; echo $ someVar`.因为while循环在管道之后,所以父shell不会知道关于`someVar`的任何信息.您可以通过使用进程替换而不是建议的管道来避免这种情况. (2认同)

cli*_*ime 1

我可能误会了,但是……

bool=false;

for i in `seq 0 ${DAEMON_COUNT}`;
do
    if [ ! -d "data$i" ]; then
            bool=true;
            echo "data$i does not exist. Creating...";
            mkdir data$i
    fi
done

if [ $bool = true ]; then 
    ... 
fi
Run Code Online (Sandbox Code Playgroud)

这是你想要的吗?